Fossil SCM

Use the Windows _wspawnv() interface with the _P_NOWAIT option to start a separate backoffice process whenever necessary. Add the backoffice-logfile setting for monitoring backoffice operation.

drh 2018-08-07 20:11 trunk
Commit 2583cae18a4bcf03408e3f56544a53de23ea53876a1551fa7948ef5ee0dcb289
2 files changed +41 -2 +7
+41 -2
--- src/backoffice.c
+++ src/backoffice.c
@@ -60,10 +60,12 @@
6060
#include "config.h"
6161
#include "backoffice.h"
6262
#include <time.h>
6363
#if defined(_WIN32)
6464
# include <windows.h>
65
+# include <stdio.h>
66
+# include <process.h>
6567
#else
6668
# include <unistd.h>
6769
# include <sys/types.h>
6870
# include <signal.h>
6971
#endif
@@ -374,10 +376,24 @@
374376
/*
375377
** This routine runs to do the backoffice processing. When adding new
376378
** backoffice processing tasks, add them here.
377379
*/
378380
void backoffice_work(void){
381
+ /* Log the backoffice run for testing purposes. For production deployments
382
+ ** the "backoffice-logfile" property should be unset and the following code
383
+ ** should be a no-op. */
384
+ char *zLog = db_get("backoffice-logfile",0);
385
+ if( zLog && zLog[0] ){
386
+ FILE *pLog = fossil_fopen(zLog, "a");
387
+ if( pLog ){
388
+ char *zDate = db_text(0, "SELECT datetime('now');");
389
+ fprintf(pLog, "%s (%d) backoffice running\n", zDate, getpid());
390
+ fclose(pLog);
391
+ }
392
+ }
393
+
394
+ /* Here is where the actual work of the backoffice happens */
379395
email_backoffice(0);
380396
}
381397
382398
/*
383399
** COMMAND: backoffice
@@ -386,12 +402,13 @@
386402
**
387403
** Run backoffice processing. This might be done by a cron job or
388404
** similar to make sure backoffice processing happens periodically.
389405
*/
390406
void backoffice_command(void){
391
- verify_all_options();
407
+ if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
392408
db_find_and_open_repository(0,0);
409
+ verify_all_options();
393410
backoffice_thread();
394411
}
395412
396413
/*
397414
** This is the main interface to backoffice from the rest of the system.
@@ -401,11 +418,32 @@
401418
void backoffice_run_if_needed(void){
402419
if( backofficeDb==0 ) return;
403420
if( strcmp(backofficeDb,"x")==0 ) return;
404421
if( g.db ) return;
405422
if( g.repositoryOpen ) return;
406
-#if !defined(_WIN32)
423
+#if defined(_WIN32)
424
+ {
425
+ int i;
426
+ intptr_t x;
427
+ char *argv[4];
428
+ wchar_t *ax[5];
429
+ argv[0] = g.nameOfExe;
430
+ argv[1] = "backoffice";
431
+ argv[2] = "-R";
432
+ argv[3] = backofficeDb;
433
+ ax[4] = 0;
434
+ for(i=0; i<=3; i++) ax[i] = fossil_utf8_to_unicode(argv[i]);
435
+ x = _wspawnv(_P_NOWAIT, ax[0], ax);
436
+ for(i=0; i<=3; i++) fossil_unicode_free(ax[i]);
437
+ if( g.fAnyTrace ){
438
+ fprintf(stderr,
439
+ "/***** Subprocess %d creates backoffice child %d *****/\n",
440
+ getpid(), (int)x);
441
+ }
442
+ if( x>=0 ) return;
443
+ }
444
+#else /* unix */
407445
{
408446
pid_t pid = fork();
409447
if( pid>0 ){
410448
/* This is the parent in a successful fork(). Return immediately. */
411449
if( g.fAnyTrace ){
@@ -415,10 +453,11 @@
415453
}
416454
return;
417455
}
418456
if( pid==0 ){
419457
/* This is the child of a successful fork(). Run backoffice. */
458
+ setsid();
420459
db_open_repository(backofficeDb);
421460
backofficeDb = "x";
422461
backoffice_thread();
423462
db_close(1);
424463
if( g.fAnyTrace ){
425464
--- src/backoffice.c
+++ src/backoffice.c
@@ -60,10 +60,12 @@
60 #include "config.h"
61 #include "backoffice.h"
62 #include <time.h>
63 #if defined(_WIN32)
64 # include <windows.h>
 
 
65 #else
66 # include <unistd.h>
67 # include <sys/types.h>
68 # include <signal.h>
69 #endif
@@ -374,10 +376,24 @@
374 /*
375 ** This routine runs to do the backoffice processing. When adding new
376 ** backoffice processing tasks, add them here.
377 */
378 void backoffice_work(void){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379 email_backoffice(0);
380 }
381
382 /*
383 ** COMMAND: backoffice
@@ -386,12 +402,13 @@
386 **
387 ** Run backoffice processing. This might be done by a cron job or
388 ** similar to make sure backoffice processing happens periodically.
389 */
390 void backoffice_command(void){
391 verify_all_options();
392 db_find_and_open_repository(0,0);
 
393 backoffice_thread();
394 }
395
396 /*
397 ** This is the main interface to backoffice from the rest of the system.
@@ -401,11 +418,32 @@
401 void backoffice_run_if_needed(void){
402 if( backofficeDb==0 ) return;
403 if( strcmp(backofficeDb,"x")==0 ) return;
404 if( g.db ) return;
405 if( g.repositoryOpen ) return;
406 #if !defined(_WIN32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407 {
408 pid_t pid = fork();
409 if( pid>0 ){
410 /* This is the parent in a successful fork(). Return immediately. */
411 if( g.fAnyTrace ){
@@ -415,10 +453,11 @@
415 }
416 return;
417 }
418 if( pid==0 ){
419 /* This is the child of a successful fork(). Run backoffice. */
 
420 db_open_repository(backofficeDb);
421 backofficeDb = "x";
422 backoffice_thread();
423 db_close(1);
424 if( g.fAnyTrace ){
425
--- src/backoffice.c
+++ src/backoffice.c
@@ -60,10 +60,12 @@
60 #include "config.h"
61 #include "backoffice.h"
62 #include <time.h>
63 #if defined(_WIN32)
64 # include <windows.h>
65 # include <stdio.h>
66 # include <process.h>
67 #else
68 # include <unistd.h>
69 # include <sys/types.h>
70 # include <signal.h>
71 #endif
@@ -374,10 +376,24 @@
376 /*
377 ** This routine runs to do the backoffice processing. When adding new
378 ** backoffice processing tasks, add them here.
379 */
380 void backoffice_work(void){
381 /* Log the backoffice run for testing purposes. For production deployments
382 ** the "backoffice-logfile" property should be unset and the following code
383 ** should be a no-op. */
384 char *zLog = db_get("backoffice-logfile",0);
385 if( zLog && zLog[0] ){
386 FILE *pLog = fossil_fopen(zLog, "a");
387 if( pLog ){
388 char *zDate = db_text(0, "SELECT datetime('now');");
389 fprintf(pLog, "%s (%d) backoffice running\n", zDate, getpid());
390 fclose(pLog);
391 }
392 }
393
394 /* Here is where the actual work of the backoffice happens */
395 email_backoffice(0);
396 }
397
398 /*
399 ** COMMAND: backoffice
@@ -386,12 +402,13 @@
402 **
403 ** Run backoffice processing. This might be done by a cron job or
404 ** similar to make sure backoffice processing happens periodically.
405 */
406 void backoffice_command(void){
407 if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
408 db_find_and_open_repository(0,0);
409 verify_all_options();
410 backoffice_thread();
411 }
412
413 /*
414 ** This is the main interface to backoffice from the rest of the system.
@@ -401,11 +418,32 @@
418 void backoffice_run_if_needed(void){
419 if( backofficeDb==0 ) return;
420 if( strcmp(backofficeDb,"x")==0 ) return;
421 if( g.db ) return;
422 if( g.repositoryOpen ) return;
423 #if defined(_WIN32)
424 {
425 int i;
426 intptr_t x;
427 char *argv[4];
428 wchar_t *ax[5];
429 argv[0] = g.nameOfExe;
430 argv[1] = "backoffice";
431 argv[2] = "-R";
432 argv[3] = backofficeDb;
433 ax[4] = 0;
434 for(i=0; i<=3; i++) ax[i] = fossil_utf8_to_unicode(argv[i]);
435 x = _wspawnv(_P_NOWAIT, ax[0], ax);
436 for(i=0; i<=3; i++) fossil_unicode_free(ax[i]);
437 if( g.fAnyTrace ){
438 fprintf(stderr,
439 "/***** Subprocess %d creates backoffice child %d *****/\n",
440 getpid(), (int)x);
441 }
442 if( x>=0 ) return;
443 }
444 #else /* unix */
445 {
446 pid_t pid = fork();
447 if( pid>0 ){
448 /* This is the parent in a successful fork(). Return immediately. */
449 if( g.fAnyTrace ){
@@ -415,10 +453,11 @@
453 }
454 return;
455 }
456 if( pid==0 ){
457 /* This is the child of a successful fork(). Run backoffice. */
458 setsid();
459 db_open_repository(backofficeDb);
460 backofficeDb = "x";
461 backoffice_thread();
462 db_close(1);
463 if( g.fAnyTrace ){
464
+7
--- src/db.c
+++ src/db.c
@@ -3033,10 +3033,17 @@
30333033
** SETTING: backoffice-nodelay boolean default=on
30343034
** If backoffice-nodelay is true, then the backoffice processing
30353035
** will never invoke sleep(). If it has nothing useful to do,
30363036
** it simply exits.
30373037
*/
3038
+/*
3039
+** SETTING: backoffice-logfile width=40
3040
+** If backoffice-logfile is not an empty string and is a valid
3041
+** filename, then a one-line message is appended to that file
3042
+** every time the backoffice runs. This can be used for debugging,
3043
+** to ensure that backoffice is running appropriately.
3044
+*/
30383045
/*
30393046
** SETTING: binary-glob width=40 versionable block-text
30403047
** The VALUE of this setting is a comma or newline-separated list of
30413048
** GLOB patterns that should be treated as binary files
30423049
** for committing and merging purposes. Example: *.jpg
30433050
--- src/db.c
+++ src/db.c
@@ -3033,10 +3033,17 @@
3033 ** SETTING: backoffice-nodelay boolean default=on
3034 ** If backoffice-nodelay is true, then the backoffice processing
3035 ** will never invoke sleep(). If it has nothing useful to do,
3036 ** it simply exits.
3037 */
 
 
 
 
 
 
 
3038 /*
3039 ** SETTING: binary-glob width=40 versionable block-text
3040 ** The VALUE of this setting is a comma or newline-separated list of
3041 ** GLOB patterns that should be treated as binary files
3042 ** for committing and merging purposes. Example: *.jpg
3043
--- src/db.c
+++ src/db.c
@@ -3033,10 +3033,17 @@
3033 ** SETTING: backoffice-nodelay boolean default=on
3034 ** If backoffice-nodelay is true, then the backoffice processing
3035 ** will never invoke sleep(). If it has nothing useful to do,
3036 ** it simply exits.
3037 */
3038 /*
3039 ** SETTING: backoffice-logfile width=40
3040 ** If backoffice-logfile is not an empty string and is a valid
3041 ** filename, then a one-line message is appended to that file
3042 ** every time the backoffice runs. This can be used for debugging,
3043 ** to ensure that backoffice is running appropriately.
3044 */
3045 /*
3046 ** SETTING: binary-glob width=40 versionable block-text
3047 ** The VALUE of this setting is a comma or newline-separated list of
3048 ** GLOB patterns that should be treated as binary files
3049 ** for committing and merging purposes. Example: *.jpg
3050

Keyboard Shortcuts

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