Fossil

Check-in [af7d67c6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the separate-process backoffice so that it works smoothly on linux. Still work to be done on Windows.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fork-backoffice
Files: files | file ages | folders
SHA3-256: af7d67c6a25f5af06284b2e0dbc8296bca9338631053ba2e207181394d4de867
User & Date: drh 2018-08-07 17:48:56
Context
2018-08-07
18:28
Improvements to comments. No code changes. Closed-Leaf check-in: 1b54dd79 user: drh tags: fork-backoffice
17:48
Fix the separate-process backoffice so that it works smoothly on linux. Still work to be done on Windows. check-in: af7d67c6 user: drh tags: fork-backoffice
15:50
Use the fork() system call (when available) to start backoffice, in an attempt to avoid unseemly delays in upstream. check-in: a4b59c32 user: drh tags: fork-backoffice
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/backoffice.c.

89
90
91
92
93
94
95













96
97
98
99
100
101
102
...
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388
** backoffice_run_if_needed() will consult this variable to see if it
** should be a no-op.
*/
static char *backofficeDb = 0;

/* End of state variables
****************************************************************************/














/*
** Parse a unsigned 64-bit integer from a string.  Return a pointer
** to the character of z[] that occurs after the integer.
*/
static const char *backofficeParseInt(const char *z, sqlite3_uint64 *pVal){
  *pVal = 0;
................................................................................
  if( g.repositoryOpen ) return;
#if !defined(_WIN32)
  {
    pid_t pid = fork();
    if( pid>0 ){
      /* This is the parent in a successful fork().  Return immediately. */
      if( g.fAnyTrace ){
        fprintf(stderr, "/***** Backoffice Child Creates as %d *****/\n",

                        (int)pid);
      }
      return;
    }
    if( pid==0 ){
      /* This is the child of a successful fork().  Run backoffice. */
      db_open_repository(backofficeDb);
      backofficeDb = "x";







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>
|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
** backoffice_run_if_needed() will consult this variable to see if it
** should be a no-op.
*/
static char *backofficeDb = 0;

/* End of state variables
****************************************************************************/

/*
** Do not allow backoffice processes to sleep waiting on a timeslot.
** They must either do their work immediately or exit.
**
** In a perfect world, this interface would not exist, as there would
** never be a problem with waiting backoffice threads.  But in some cases
** a backoffice will delay a UI thread, so we don't want them to run for
** longer than needed.
*/
void backoffice_no_delay(void){
  backofficeNoDelay = 1;
}

/*
** Parse a unsigned 64-bit integer from a string.  Return a pointer
** to the character of z[] that occurs after the integer.
*/
static const char *backofficeParseInt(const char *z, sqlite3_uint64 *pVal){
  *pVal = 0;
................................................................................
  if( g.repositoryOpen ) return;
#if !defined(_WIN32)
  {
    pid_t pid = fork();
    if( pid>0 ){
      /* This is the parent in a successful fork().  Return immediately. */
      if( g.fAnyTrace ){
        fprintf(stderr, 
          "/***** Subprocess %d creates backoffice child %d *****/\n",
          getpid(), (int)pid);
      }
      return;
    }
    if( pid==0 ){
      /* This is the child of a successful fork().  Run backoffice. */
      db_open_repository(backofficeDb);
      backofficeDb = "x";

Changes to src/cgi.c.

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  fflush(g.httpOut);
  CGIDEBUG(("DONE\n"));

  /* After the webpage has been sent, do any useful background
  ** processing.
  */
  g.cgiOutput = 2;
  if( g.db!=0 && iReplyStatus==200 && !g.fSshClient ){
    fclose(g.httpOut);
#ifdef _WIN32
    g.httpOut = fossil_fopen("NUL", "wb");
#else
    g.httpOut = fossil_fopen("/dev/null", "wb");
#endif
    if( g.httpOut==0 ){
      fossil_warning("failed ot open /dev/null");
    }else{
      backoffice_check_if_needed();
    }
  }
}

/*
** Do a redirect request to the URL given in the argument.
**
** The URL must be relative to the base of the fossil server.







|
<
<
<
<
<
<
<
<
<
|
<







342
343
344
345
346
347
348
349









350

351
352
353
354
355
356
357
  fflush(g.httpOut);
  CGIDEBUG(("DONE\n"));

  /* After the webpage has been sent, do any useful background
  ** processing.
  */
  g.cgiOutput = 2;
  if( g.db!=0 && iReplyStatus==200 ){









    backoffice_check_if_needed();

  }
}

/*
** Do a redirect request to the URL given in the argument.
**
** The URL must be relative to the base of the fossil server.

Changes to src/forum.c.

942
943
944
945
946
947
948

949
950
    const char *zTitle = db_column_text(&q, 2);
    @ <tr><td>%h(zAge) ago</td>
    @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a>
    @ </tr>
    fossil_free(zAge);
  }
  @ </table></div>

  style_footer();
}







>


942
943
944
945
946
947
948
949
950
951
    const char *zTitle = db_column_text(&q, 2);
    @ <tr><td>%h(zAge) ago</td>
    @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a>
    @ </tr>
    fossil_free(zAge);
  }
  @ </table></div>
  db_finalize(&q);
  style_footer();
}

Changes to src/main.c.

2295
2296
2297
2298
2299
2300
2301

2302
2303
2304
2305
2306
2307
2308
....
2361
2362
2363
2364
2365
2366
2367

2368
2369
2370
2371
2372
2373
2374
**   --files GLOB     comma-separate glob patterns for static file to serve
**   --localauth      enable automatic login for local connections
**   --host NAME      specify hostname of the server
**   --https          signal a request coming in via https
**   --in FILE        Take input from FILE instead of standard input
**   --ipaddr ADDR    Assume the request comes from the given IP address
**   --nocompress     do not compress HTTP replies

**   --nojail         drop root privilege but do not enter the chroot jail
**   --nossl          signal that no SSL connections are available
**   --notfound URL   use URL as "HTTP 404, object not found" page.
**   --out FILE       write results to FILE instead of to standard output
**   --repolist       If REPOSITORY is directory, URL "/" lists all repos
**   --scgi           Interpret input as SCGI rather than HTTP
**   --skin LABEL     Use override skin LABEL
................................................................................
    if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile);
  }else{
    g.httpOut = stdout;
  }
  zIpAddr = find_option("ipaddr",0,1);
  useSCGI = find_option("scgi", 0, 0)!=0;
  zAltBase = find_option("baseurl", 0, 1);

  if( zAltBase ) set_base_url(zAltBase);
  if( find_option("https",0,0)!=0 ){
    zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
    cgi_replace_parameter("HTTPS","on");
  }
  zHost = find_option("host", 0, 1);
  if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);







>







 







>







2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
....
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
**   --files GLOB     comma-separate glob patterns for static file to serve
**   --localauth      enable automatic login for local connections
**   --host NAME      specify hostname of the server
**   --https          signal a request coming in via https
**   --in FILE        Take input from FILE instead of standard input
**   --ipaddr ADDR    Assume the request comes from the given IP address
**   --nocompress     do not compress HTTP replies
**   --nodelay        omit backoffice processing if it would delay process exit
**   --nojail         drop root privilege but do not enter the chroot jail
**   --nossl          signal that no SSL connections are available
**   --notfound URL   use URL as "HTTP 404, object not found" page.
**   --out FILE       write results to FILE instead of to standard output
**   --repolist       If REPOSITORY is directory, URL "/" lists all repos
**   --scgi           Interpret input as SCGI rather than HTTP
**   --skin LABEL     Use override skin LABEL
................................................................................
    if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile);
  }else{
    g.httpOut = stdout;
  }
  zIpAddr = find_option("ipaddr",0,1);
  useSCGI = find_option("scgi", 0, 0)!=0;
  zAltBase = find_option("baseurl", 0, 1);
  if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
  if( zAltBase ) set_base_url(zAltBase);
  if( find_option("https",0,0)!=0 ){
    zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
    cgi_replace_parameter("HTTPS","on");
  }
  zHost = find_option("host", 0, 1);
  if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);

Changes to src/printf.c.

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
  int rc = 1;
  char z[1000];
  static int once = 0;

  if( once ) exit(1);
  once = 1;
  mainInFatalError = 1;
  db_force_rollback();
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
  va_end(ap);
  if( g.fAnyTrace ){
    fprintf(stderr, "/***** panic on %d *****/\n", getpid());
  }
  fossil_errorlog("panic: %s", z);







|







1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
  int rc = 1;
  char z[1000];
  static int once = 0;

  if( once ) exit(1);
  once = 1;
  mainInFatalError = 1;
  /* db_force_rollback(); */
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
  va_end(ap);
  if( g.fAnyTrace ){
    fprintf(stderr, "/***** panic on %d *****/\n", getpid());
  }
  fossil_errorlog("panic: %s", z);