Fossil SCM

Initial code for implementing the idle-timeout feature for "fossil ui". Seems to work in preliminary tests on unix. Windows implementation is incomplete and untested.

drh 2020-04-09 16:14 trunk
Commit 39a899e4cf7da42e2f31802488160385ba134527525fa7d2c306691e03237c88
+9 -1
--- src/cgi.c
+++ src/cgi.c
@@ -1992,10 +1992,11 @@
19921992
*/
19931993
int cgi_http_server(
19941994
int mnPort, int mxPort, /* Range of TCP ports to try */
19951995
const char *zBrowser, /* Run this browser, if not NULL */
19961996
const char *zIpAddr, /* Bind to this IP address, if not null */
1997
+ int iIdleTimeout, /* Stop after this many seconds of inactivity */
19971998
int flags /* HTTP_SERVER_* flags */
19981999
){
19992000
#if defined(_WIN32)
20002001
/* Use win32_http_server() instead */
20012002
fossil_exit(1);
@@ -2008,11 +2009,12 @@
20082009
int child; /* PID of the child process */
20092010
int nchildren = 0; /* Number of child processes */
20102011
struct timeval delay; /* How long to wait inside select() */
20112012
struct sockaddr_in inaddr; /* The socket address */
20122013
int opt = 1; /* setsockopt flag */
2013
- int iPort = mnPort;
2014
+ int iPort = mnPort; /* TCP port to use */
2015
+ time_t stopTime; /* When to timeout */
20142016
20152017
while( iPort<=mxPort ){
20162018
memset(&inaddr, 0, sizeof(inaddr));
20172019
inaddr.sin_family = AF_INET;
20182020
if( zIpAddr ){
@@ -2070,10 +2072,11 @@
20702072
#endif
20712073
if( system(zBrowser)<0 ){
20722074
fossil_warning("cannot start browser: %s\n", zBrowser);
20732075
}
20742076
}
2077
+ if( iIdleTimeout>0 ) stopTime = time(0)+iIdleTimeout;
20752078
while( 1 ){
20762079
#if FOSSIL_MAX_CONNECTIONS>0
20772080
while( nchildren>=FOSSIL_MAX_CONNECTIONS ){
20782081
if( wait(0)>=0 ) nchildren--;
20792082
}
@@ -2086,10 +2089,11 @@
20862089
select( listener+1, &readfds, 0, 0, &delay);
20872090
if( FD_ISSET(listener, &readfds) ){
20882091
lenaddr = sizeof(inaddr);
20892092
connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
20902093
if( connection>=0 ){
2094
+ if( iIdleTimeout>0 ) stopTime = time(0)+iIdleTimeout;
20912095
child = fork();
20922096
if( child!=0 ){
20932097
if( child>0 ){
20942098
nchildren++;
20952099
nRequest++;
@@ -2125,10 +2129,14 @@
21252129
fprintf(stderr, "/***** Child %d exited on signal %d (%s) *****/\n",
21262130
x, WTERMSIG(iStatus), strsignal(WTERMSIG(iStatus)));
21272131
}
21282132
nchildren--;
21292133
}
2134
+ }
2135
+ /* Stop serving if idle for too long */
2136
+ if( iIdleTimeout>0 && stopTime<time(0) ){
2137
+ fossil_exit(0);
21302138
}
21312139
}
21322140
/* NOT REACHED */
21332141
fossil_exit(1);
21342142
#endif
21352143
--- src/cgi.c
+++ src/cgi.c
@@ -1992,10 +1992,11 @@
1992 */
1993 int cgi_http_server(
1994 int mnPort, int mxPort, /* Range of TCP ports to try */
1995 const char *zBrowser, /* Run this browser, if not NULL */
1996 const char *zIpAddr, /* Bind to this IP address, if not null */
 
1997 int flags /* HTTP_SERVER_* flags */
1998 ){
1999 #if defined(_WIN32)
2000 /* Use win32_http_server() instead */
2001 fossil_exit(1);
@@ -2008,11 +2009,12 @@
2008 int child; /* PID of the child process */
2009 int nchildren = 0; /* Number of child processes */
2010 struct timeval delay; /* How long to wait inside select() */
2011 struct sockaddr_in inaddr; /* The socket address */
2012 int opt = 1; /* setsockopt flag */
2013 int iPort = mnPort;
 
2014
2015 while( iPort<=mxPort ){
2016 memset(&inaddr, 0, sizeof(inaddr));
2017 inaddr.sin_family = AF_INET;
2018 if( zIpAddr ){
@@ -2070,10 +2072,11 @@
2070 #endif
2071 if( system(zBrowser)<0 ){
2072 fossil_warning("cannot start browser: %s\n", zBrowser);
2073 }
2074 }
 
2075 while( 1 ){
2076 #if FOSSIL_MAX_CONNECTIONS>0
2077 while( nchildren>=FOSSIL_MAX_CONNECTIONS ){
2078 if( wait(0)>=0 ) nchildren--;
2079 }
@@ -2086,10 +2089,11 @@
2086 select( listener+1, &readfds, 0, 0, &delay);
2087 if( FD_ISSET(listener, &readfds) ){
2088 lenaddr = sizeof(inaddr);
2089 connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
2090 if( connection>=0 ){
 
2091 child = fork();
2092 if( child!=0 ){
2093 if( child>0 ){
2094 nchildren++;
2095 nRequest++;
@@ -2125,10 +2129,14 @@
2125 fprintf(stderr, "/***** Child %d exited on signal %d (%s) *****/\n",
2126 x, WTERMSIG(iStatus), strsignal(WTERMSIG(iStatus)));
2127 }
2128 nchildren--;
2129 }
 
 
 
 
2130 }
2131 }
2132 /* NOT REACHED */
2133 fossil_exit(1);
2134 #endif
2135
--- src/cgi.c
+++ src/cgi.c
@@ -1992,10 +1992,11 @@
1992 */
1993 int cgi_http_server(
1994 int mnPort, int mxPort, /* Range of TCP ports to try */
1995 const char *zBrowser, /* Run this browser, if not NULL */
1996 const char *zIpAddr, /* Bind to this IP address, if not null */
1997 int iIdleTimeout, /* Stop after this many seconds of inactivity */
1998 int flags /* HTTP_SERVER_* flags */
1999 ){
2000 #if defined(_WIN32)
2001 /* Use win32_http_server() instead */
2002 fossil_exit(1);
@@ -2008,11 +2009,12 @@
2009 int child; /* PID of the child process */
2010 int nchildren = 0; /* Number of child processes */
2011 struct timeval delay; /* How long to wait inside select() */
2012 struct sockaddr_in inaddr; /* The socket address */
2013 int opt = 1; /* setsockopt flag */
2014 int iPort = mnPort; /* TCP port to use */
2015 time_t stopTime; /* When to timeout */
2016
2017 while( iPort<=mxPort ){
2018 memset(&inaddr, 0, sizeof(inaddr));
2019 inaddr.sin_family = AF_INET;
2020 if( zIpAddr ){
@@ -2070,10 +2072,11 @@
2072 #endif
2073 if( system(zBrowser)<0 ){
2074 fossil_warning("cannot start browser: %s\n", zBrowser);
2075 }
2076 }
2077 if( iIdleTimeout>0 ) stopTime = time(0)+iIdleTimeout;
2078 while( 1 ){
2079 #if FOSSIL_MAX_CONNECTIONS>0
2080 while( nchildren>=FOSSIL_MAX_CONNECTIONS ){
2081 if( wait(0)>=0 ) nchildren--;
2082 }
@@ -2086,10 +2089,11 @@
2089 select( listener+1, &readfds, 0, 0, &delay);
2090 if( FD_ISSET(listener, &readfds) ){
2091 lenaddr = sizeof(inaddr);
2092 connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
2093 if( connection>=0 ){
2094 if( iIdleTimeout>0 ) stopTime = time(0)+iIdleTimeout;
2095 child = fork();
2096 if( child!=0 ){
2097 if( child>0 ){
2098 nchildren++;
2099 nRequest++;
@@ -2125,10 +2129,14 @@
2129 fprintf(stderr, "/***** Child %d exited on signal %d (%s) *****/\n",
2130 x, WTERMSIG(iStatus), strsignal(WTERMSIG(iStatus)));
2131 }
2132 nchildren--;
2133 }
2134 }
2135 /* Stop serving if idle for too long */
2136 if( iIdleTimeout>0 && stopTime<time(0) ){
2137 fossil_exit(0);
2138 }
2139 }
2140 /* NOT REACHED */
2141 fossil_exit(1);
2142 #endif
2143
+24 -2
--- src/main.c
+++ src/main.c
@@ -1256,10 +1256,20 @@
12561256
@ %h(blob_str(&versionInfo))
12571257
@ </pre>
12581258
style_footer();
12591259
}
12601260
1261
+/*
1262
+** WEBPAGE: noop
1263
+**
1264
+** Send back an empty HTTP reply. Deliver no content.
1265
+*/
1266
+void noop_page(void){
1267
+ fossil_free(style_csp(1));
1268
+ cgi_set_content_type("text/plain");
1269
+}
1270
+
12611271
12621272
/*
12631273
** Set the g.zBaseURL value to the full URL for the toplevel of
12641274
** the fossil tree. Set g.zTop to g.zBaseURL without the
12651275
** leading "http://" and the host and port.
@@ -2361,10 +2371,11 @@
23612371
** --files GLOB comma-separate glob patterns for static file to serve
23622372
** --host NAME specify hostname of the server
23632373
** --https signal a request coming in via https
23642374
** --in FILE Take input from FILE instead of standard input
23652375
** --ipaddr ADDR Assume the request comes from the given IP address
2376
+** --keep-alive Include "keepalive.js" in HTML pages
23662377
** --localauth enable automatic login for local connections
23672378
** --nocompress do not compress HTTP replies
23682379
** --nodelay omit backoffice processing if it would delay process exit
23692380
** --nojail drop root privilege but do not enter the chroot jail
23702381
** --nossl signal that no SSL connections are available
@@ -2440,10 +2451,11 @@
24402451
zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
24412452
cgi_replace_parameter("HTTPS","on");
24422453
}
24432454
zHost = find_option("host", 0, 1);
24442455
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
2456
+ if( find_option("keep-alive",0,0) ) style_load_js("keepalive.js");
24452457
24462458
#if defined(_WIN32) && USE_SEE
24472459
zPidKey = find_option("usepidkey", 0, 1);
24482460
if( zPidKey ){
24492461
DWORD processId = 0;
@@ -2624,10 +2636,11 @@
26242636
** Options:
26252637
** --baseurl URL Use URL as the base (useful for reverse proxies)
26262638
** --create Create a new REPOSITORY if it does not already exist
26272639
** --extroot DIR Document root for the /ext extension mechanism
26282640
** --files GLOBLIST Comma-separated list of glob patterns for static files
2641
+** --idle-timeout N Exit if no HTTP requests received for N seconds
26292642
** --localauth enable automatic login for requests from localhost
26302643
** --localhost listen on 127.0.0.1 only (always true for "ui")
26312644
** --https Indicates that the input is coming through a reverse
26322645
** proxy that has already translated HTTPS into HTTP.
26332646
** --max-latency N Do not let any single HTTP request run for more than N
@@ -2663,10 +2676,12 @@
26632676
int allowRepoList; /* List repositories on URL "/" */
26642677
const char *zAltBase; /* Argument to the --baseurl option */
26652678
const char *zFileGlob; /* Static content must match this */
26662679
char *zIpAddr = 0; /* Bind to this IP address */
26672680
int fCreate = 0; /* The --create flag */
2681
+ const char *zIdleTimeout; /* Value of the --idle-timeout flag */
2682
+ int iIdle = 0; /* Idle timeout value */
26682683
const char *zInitPage = 0; /* Start on this page. --page option */
26692684
#if defined(_WIN32) && USE_SEE
26702685
const char *zPidKey;
26712686
#endif
26722687
@@ -2696,11 +2711,17 @@
26962711
Th_InitTraceLog();
26972712
zPort = find_option("port", "P", 1);
26982713
isUiCmd = g.argv[1][0]=='u';
26992714
if( isUiCmd ){
27002715
zInitPage = find_option("page", 0, 1);
2716
+ iIdle = 60;
2717
+ }
2718
+ zIdleTimeout = find_option("idle-timeout",0,1);
2719
+ if( zIdleTimeout ){
2720
+ iIdle = atoi(zIdleTimeout);
27012721
}
2722
+
27022723
zNotFound = find_option("notfound", 0, 1);
27032724
allowRepoList = find_option("repolist",0,0)!=0;
27042725
if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
27052726
zAltBase = find_option("baseurl", 0, 1);
27062727
fCreate = find_option("create",0,0)!=0;
@@ -2794,11 +2815,11 @@
27942815
}
27952816
}
27962817
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
27972818
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
27982819
db_close(1);
2799
- if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2820
+ if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, iIdle, flags) ){
28002821
fossil_fatal("unable to listen on TCP socket %d", iPort);
28012822
}
28022823
/* For the parent process, the cgi_http_server() command above never
28032824
** returns (except in the case of an error). Instead, for each incoming
28042825
** client connection, a child process is created, file descriptors 0
@@ -2834,10 +2855,11 @@
28342855
if( flags & HTTP_SERVER_SCGI ){
28352856
cgi_handle_scgi_request();
28362857
}else{
28372858
cgi_handle_http_request(0);
28382859
}
2860
+ if( iIdle>0 ) style_load_js("keepalive.js");
28392861
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
28402862
if( g.fAnyTrace ){
28412863
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
28422864
getpid());
28432865
}
@@ -2862,11 +2884,11 @@
28622884
if( allowRepoList ){
28632885
flags |= HTTP_SERVER_REPOLIST;
28642886
}
28652887
if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){
28662888
win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile,
2867
- zAltBase, zNotFound, zFileGlob, zIpAddr, flags);
2889
+ zAltBase, zNotFound, zFileGlob, zIpAddr, iIdle, flags);
28682890
}
28692891
#endif
28702892
}
28712893
28722894
/*
28732895
--- src/main.c
+++ src/main.c
@@ -1256,10 +1256,20 @@
1256 @ %h(blob_str(&versionInfo))
1257 @ </pre>
1258 style_footer();
1259 }
1260
 
 
 
 
 
 
 
 
 
 
1261
1262 /*
1263 ** Set the g.zBaseURL value to the full URL for the toplevel of
1264 ** the fossil tree. Set g.zTop to g.zBaseURL without the
1265 ** leading "http://" and the host and port.
@@ -2361,10 +2371,11 @@
2361 ** --files GLOB comma-separate glob patterns for static file to serve
2362 ** --host NAME specify hostname of the server
2363 ** --https signal a request coming in via https
2364 ** --in FILE Take input from FILE instead of standard input
2365 ** --ipaddr ADDR Assume the request comes from the given IP address
 
2366 ** --localauth enable automatic login for local connections
2367 ** --nocompress do not compress HTTP replies
2368 ** --nodelay omit backoffice processing if it would delay process exit
2369 ** --nojail drop root privilege but do not enter the chroot jail
2370 ** --nossl signal that no SSL connections are available
@@ -2440,10 +2451,11 @@
2440 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
2441 cgi_replace_parameter("HTTPS","on");
2442 }
2443 zHost = find_option("host", 0, 1);
2444 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
 
2445
2446 #if defined(_WIN32) && USE_SEE
2447 zPidKey = find_option("usepidkey", 0, 1);
2448 if( zPidKey ){
2449 DWORD processId = 0;
@@ -2624,10 +2636,11 @@
2624 ** Options:
2625 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2626 ** --create Create a new REPOSITORY if it does not already exist
2627 ** --extroot DIR Document root for the /ext extension mechanism
2628 ** --files GLOBLIST Comma-separated list of glob patterns for static files
 
2629 ** --localauth enable automatic login for requests from localhost
2630 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2631 ** --https Indicates that the input is coming through a reverse
2632 ** proxy that has already translated HTTPS into HTTP.
2633 ** --max-latency N Do not let any single HTTP request run for more than N
@@ -2663,10 +2676,12 @@
2663 int allowRepoList; /* List repositories on URL "/" */
2664 const char *zAltBase; /* Argument to the --baseurl option */
2665 const char *zFileGlob; /* Static content must match this */
2666 char *zIpAddr = 0; /* Bind to this IP address */
2667 int fCreate = 0; /* The --create flag */
 
 
2668 const char *zInitPage = 0; /* Start on this page. --page option */
2669 #if defined(_WIN32) && USE_SEE
2670 const char *zPidKey;
2671 #endif
2672
@@ -2696,11 +2711,17 @@
2696 Th_InitTraceLog();
2697 zPort = find_option("port", "P", 1);
2698 isUiCmd = g.argv[1][0]=='u';
2699 if( isUiCmd ){
2700 zInitPage = find_option("page", 0, 1);
 
 
 
 
 
2701 }
 
2702 zNotFound = find_option("notfound", 0, 1);
2703 allowRepoList = find_option("repolist",0,0)!=0;
2704 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
2705 zAltBase = find_option("baseurl", 0, 1);
2706 fCreate = find_option("create",0,0)!=0;
@@ -2794,11 +2815,11 @@
2794 }
2795 }
2796 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2797 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2798 db_close(1);
2799 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2800 fossil_fatal("unable to listen on TCP socket %d", iPort);
2801 }
2802 /* For the parent process, the cgi_http_server() command above never
2803 ** returns (except in the case of an error). Instead, for each incoming
2804 ** client connection, a child process is created, file descriptors 0
@@ -2834,10 +2855,11 @@
2834 if( flags & HTTP_SERVER_SCGI ){
2835 cgi_handle_scgi_request();
2836 }else{
2837 cgi_handle_http_request(0);
2838 }
 
2839 process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
2840 if( g.fAnyTrace ){
2841 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
2842 getpid());
2843 }
@@ -2862,11 +2884,11 @@
2862 if( allowRepoList ){
2863 flags |= HTTP_SERVER_REPOLIST;
2864 }
2865 if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){
2866 win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile,
2867 zAltBase, zNotFound, zFileGlob, zIpAddr, flags);
2868 }
2869 #endif
2870 }
2871
2872 /*
2873
--- src/main.c
+++ src/main.c
@@ -1256,10 +1256,20 @@
1256 @ %h(blob_str(&versionInfo))
1257 @ </pre>
1258 style_footer();
1259 }
1260
1261 /*
1262 ** WEBPAGE: noop
1263 **
1264 ** Send back an empty HTTP reply. Deliver no content.
1265 */
1266 void noop_page(void){
1267 fossil_free(style_csp(1));
1268 cgi_set_content_type("text/plain");
1269 }
1270
1271
1272 /*
1273 ** Set the g.zBaseURL value to the full URL for the toplevel of
1274 ** the fossil tree. Set g.zTop to g.zBaseURL without the
1275 ** leading "http://" and the host and port.
@@ -2361,10 +2371,11 @@
2371 ** --files GLOB comma-separate glob patterns for static file to serve
2372 ** --host NAME specify hostname of the server
2373 ** --https signal a request coming in via https
2374 ** --in FILE Take input from FILE instead of standard input
2375 ** --ipaddr ADDR Assume the request comes from the given IP address
2376 ** --keep-alive Include "keepalive.js" in HTML pages
2377 ** --localauth enable automatic login for local connections
2378 ** --nocompress do not compress HTTP replies
2379 ** --nodelay omit backoffice processing if it would delay process exit
2380 ** --nojail drop root privilege but do not enter the chroot jail
2381 ** --nossl signal that no SSL connections are available
@@ -2440,10 +2451,11 @@
2451 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
2452 cgi_replace_parameter("HTTPS","on");
2453 }
2454 zHost = find_option("host", 0, 1);
2455 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
2456 if( find_option("keep-alive",0,0) ) style_load_js("keepalive.js");
2457
2458 #if defined(_WIN32) && USE_SEE
2459 zPidKey = find_option("usepidkey", 0, 1);
2460 if( zPidKey ){
2461 DWORD processId = 0;
@@ -2624,10 +2636,11 @@
2636 ** Options:
2637 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2638 ** --create Create a new REPOSITORY if it does not already exist
2639 ** --extroot DIR Document root for the /ext extension mechanism
2640 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2641 ** --idle-timeout N Exit if no HTTP requests received for N seconds
2642 ** --localauth enable automatic login for requests from localhost
2643 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2644 ** --https Indicates that the input is coming through a reverse
2645 ** proxy that has already translated HTTPS into HTTP.
2646 ** --max-latency N Do not let any single HTTP request run for more than N
@@ -2663,10 +2676,12 @@
2676 int allowRepoList; /* List repositories on URL "/" */
2677 const char *zAltBase; /* Argument to the --baseurl option */
2678 const char *zFileGlob; /* Static content must match this */
2679 char *zIpAddr = 0; /* Bind to this IP address */
2680 int fCreate = 0; /* The --create flag */
2681 const char *zIdleTimeout; /* Value of the --idle-timeout flag */
2682 int iIdle = 0; /* Idle timeout value */
2683 const char *zInitPage = 0; /* Start on this page. --page option */
2684 #if defined(_WIN32) && USE_SEE
2685 const char *zPidKey;
2686 #endif
2687
@@ -2696,11 +2711,17 @@
2711 Th_InitTraceLog();
2712 zPort = find_option("port", "P", 1);
2713 isUiCmd = g.argv[1][0]=='u';
2714 if( isUiCmd ){
2715 zInitPage = find_option("page", 0, 1);
2716 iIdle = 60;
2717 }
2718 zIdleTimeout = find_option("idle-timeout",0,1);
2719 if( zIdleTimeout ){
2720 iIdle = atoi(zIdleTimeout);
2721 }
2722
2723 zNotFound = find_option("notfound", 0, 1);
2724 allowRepoList = find_option("repolist",0,0)!=0;
2725 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
2726 zAltBase = find_option("baseurl", 0, 1);
2727 fCreate = find_option("create",0,0)!=0;
@@ -2794,11 +2815,11 @@
2815 }
2816 }
2817 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2818 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2819 db_close(1);
2820 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, iIdle, flags) ){
2821 fossil_fatal("unable to listen on TCP socket %d", iPort);
2822 }
2823 /* For the parent process, the cgi_http_server() command above never
2824 ** returns (except in the case of an error). Instead, for each incoming
2825 ** client connection, a child process is created, file descriptors 0
@@ -2834,10 +2855,11 @@
2855 if( flags & HTTP_SERVER_SCGI ){
2856 cgi_handle_scgi_request();
2857 }else{
2858 cgi_handle_http_request(0);
2859 }
2860 if( iIdle>0 ) style_load_js("keepalive.js");
2861 process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
2862 if( g.fAnyTrace ){
2863 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
2864 getpid());
2865 }
@@ -2862,11 +2884,11 @@
2884 if( allowRepoList ){
2885 flags |= HTTP_SERVER_REPOLIST;
2886 }
2887 if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){
2888 win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile,
2889 zAltBase, zNotFound, zFileGlob, zIpAddr, iIdle, flags);
2890 }
2891 #endif
2892 }
2893
2894 /*
2895
--- src/main.mk
+++ src/main.mk
@@ -218,10 +218,11 @@
218218
$(SRCDIR)/copybtn.js \
219219
$(SRCDIR)/diff.tcl \
220220
$(SRCDIR)/forum.js \
221221
$(SRCDIR)/graph.js \
222222
$(SRCDIR)/href.js \
223
+ $(SRCDIR)/keepalive.js \
223224
$(SRCDIR)/login.js \
224225
$(SRCDIR)/markdown.md \
225226
$(SRCDIR)/menu.js \
226227
$(SRCDIR)/sbsdiff.js \
227228
$(SRCDIR)/scroll.js \
228229
--- src/main.mk
+++ src/main.mk
@@ -218,10 +218,11 @@
218 $(SRCDIR)/copybtn.js \
219 $(SRCDIR)/diff.tcl \
220 $(SRCDIR)/forum.js \
221 $(SRCDIR)/graph.js \
222 $(SRCDIR)/href.js \
 
223 $(SRCDIR)/login.js \
224 $(SRCDIR)/markdown.md \
225 $(SRCDIR)/menu.js \
226 $(SRCDIR)/sbsdiff.js \
227 $(SRCDIR)/scroll.js \
228
--- src/main.mk
+++ src/main.mk
@@ -218,10 +218,11 @@
218 $(SRCDIR)/copybtn.js \
219 $(SRCDIR)/diff.tcl \
220 $(SRCDIR)/forum.js \
221 $(SRCDIR)/graph.js \
222 $(SRCDIR)/href.js \
223 $(SRCDIR)/keepalive.js \
224 $(SRCDIR)/login.js \
225 $(SRCDIR)/markdown.md \
226 $(SRCDIR)/menu.js \
227 $(SRCDIR)/sbsdiff.js \
228 $(SRCDIR)/scroll.js \
229
--- src/winhttp.c
+++ src/winhttp.c
@@ -519,10 +519,11 @@
519519
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
520520
const char *zBaseUrl, /* The --baseurl option, or NULL */
521521
const char *zNotFound, /* The --notfound option, or NULL */
522522
const char *zFileGlob, /* The --fileglob option, or NULL */
523523
const char *zIpAddr, /* Bind to this IP address, if not NULL */
524
+ int idleTimeout, /* Idle timeout in seconds. 0 means none */
524525
int flags /* One or more HTTP_SERVER_ flags */
525526
){
526527
HANDLE hStoppedEvent;
527528
WSADATA wd;
528529
DualSocket ds;
@@ -553,10 +554,13 @@
553554
blob_appendf(&options, " --localauth");
554555
}
555556
if( g.thTrace ){
556557
blob_appendf(&options, " --th-trace");
557558
}
559
+ if( idleTimeout>0 ){
560
+ blob_appendf(&options, " --keep-alive");
561
+ }
558562
if( flags & HTTP_SERVER_REPOLIST ){
559563
blob_appendf(&options, " --repolist");
560564
}
561565
zSkin = skin_in_use();
562566
if( zSkin ){
563567
--- src/winhttp.c
+++ src/winhttp.c
@@ -519,10 +519,11 @@
519 const char *zStopper, /* Stop server when this file is exists (Or NULL) */
520 const char *zBaseUrl, /* The --baseurl option, or NULL */
521 const char *zNotFound, /* The --notfound option, or NULL */
522 const char *zFileGlob, /* The --fileglob option, or NULL */
523 const char *zIpAddr, /* Bind to this IP address, if not NULL */
 
524 int flags /* One or more HTTP_SERVER_ flags */
525 ){
526 HANDLE hStoppedEvent;
527 WSADATA wd;
528 DualSocket ds;
@@ -553,10 +554,13 @@
553 blob_appendf(&options, " --localauth");
554 }
555 if( g.thTrace ){
556 blob_appendf(&options, " --th-trace");
557 }
 
 
 
558 if( flags & HTTP_SERVER_REPOLIST ){
559 blob_appendf(&options, " --repolist");
560 }
561 zSkin = skin_in_use();
562 if( zSkin ){
563
--- src/winhttp.c
+++ src/winhttp.c
@@ -519,10 +519,11 @@
519 const char *zStopper, /* Stop server when this file is exists (Or NULL) */
520 const char *zBaseUrl, /* The --baseurl option, or NULL */
521 const char *zNotFound, /* The --notfound option, or NULL */
522 const char *zFileGlob, /* The --fileglob option, or NULL */
523 const char *zIpAddr, /* Bind to this IP address, if not NULL */
524 int idleTimeout, /* Idle timeout in seconds. 0 means none */
525 int flags /* One or more HTTP_SERVER_ flags */
526 ){
527 HANDLE hStoppedEvent;
528 WSADATA wd;
529 DualSocket ds;
@@ -553,10 +554,13 @@
554 blob_appendf(&options, " --localauth");
555 }
556 if( g.thTrace ){
557 blob_appendf(&options, " --th-trace");
558 }
559 if( idleTimeout>0 ){
560 blob_appendf(&options, " --keep-alive");
561 }
562 if( flags & HTTP_SERVER_REPOLIST ){
563 blob_appendf(&options, " --repolist");
564 }
565 zSkin = skin_in_use();
566 if( zSkin ){
567
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -640,10 +640,11 @@
640640
$(SRCDIR)/copybtn.js \
641641
$(SRCDIR)/diff.tcl \
642642
$(SRCDIR)/forum.js \
643643
$(SRCDIR)/graph.js \
644644
$(SRCDIR)/href.js \
645
+ $(SRCDIR)/keepalive.js \
645646
$(SRCDIR)/login.js \
646647
$(SRCDIR)/markdown.md \
647648
$(SRCDIR)/menu.js \
648649
$(SRCDIR)/sbsdiff.js \
649650
$(SRCDIR)/scroll.js \
650651
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -640,10 +640,11 @@
640 $(SRCDIR)/copybtn.js \
641 $(SRCDIR)/diff.tcl \
642 $(SRCDIR)/forum.js \
643 $(SRCDIR)/graph.js \
644 $(SRCDIR)/href.js \
 
645 $(SRCDIR)/login.js \
646 $(SRCDIR)/markdown.md \
647 $(SRCDIR)/menu.js \
648 $(SRCDIR)/sbsdiff.js \
649 $(SRCDIR)/scroll.js \
650
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -640,10 +640,11 @@
640 $(SRCDIR)/copybtn.js \
641 $(SRCDIR)/diff.tcl \
642 $(SRCDIR)/forum.js \
643 $(SRCDIR)/graph.js \
644 $(SRCDIR)/href.js \
645 $(SRCDIR)/keepalive.js \
646 $(SRCDIR)/login.js \
647 $(SRCDIR)/markdown.md \
648 $(SRCDIR)/menu.js \
649 $(SRCDIR)/sbsdiff.js \
650 $(SRCDIR)/scroll.js \
651
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -547,10 +547,11 @@
547547
$(SRCDIR)\copybtn.js \
548548
$(SRCDIR)\diff.tcl \
549549
$(SRCDIR)\forum.js \
550550
$(SRCDIR)\graph.js \
551551
$(SRCDIR)\href.js \
552
+ $(SRCDIR)\keepalive.js \
552553
$(SRCDIR)\login.js \
553554
$(SRCDIR)\markdown.md \
554555
$(SRCDIR)\menu.js \
555556
$(SRCDIR)\sbsdiff.js \
556557
$(SRCDIR)\scroll.js \
557558
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -547,10 +547,11 @@
547 $(SRCDIR)\copybtn.js \
548 $(SRCDIR)\diff.tcl \
549 $(SRCDIR)\forum.js \
550 $(SRCDIR)\graph.js \
551 $(SRCDIR)\href.js \
 
552 $(SRCDIR)\login.js \
553 $(SRCDIR)\markdown.md \
554 $(SRCDIR)\menu.js \
555 $(SRCDIR)\sbsdiff.js \
556 $(SRCDIR)\scroll.js \
557
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -547,10 +547,11 @@
547 $(SRCDIR)\copybtn.js \
548 $(SRCDIR)\diff.tcl \
549 $(SRCDIR)\forum.js \
550 $(SRCDIR)\graph.js \
551 $(SRCDIR)\href.js \
552 $(SRCDIR)\keepalive.js \
553 $(SRCDIR)\login.js \
554 $(SRCDIR)\markdown.md \
555 $(SRCDIR)\menu.js \
556 $(SRCDIR)\sbsdiff.js \
557 $(SRCDIR)\scroll.js \
558

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button