@@ -174,6 +174,8 @@ static int bgpipe[2] = {-1, -1};
174
174
/* Handle to child process */
175
175
static pid_t bgchild = -1 ;
176
176
static bool in_log_streamer = false;
177
+ /* Flag to indicate if child process exited unexpectedly */
178
+ static volatile sig_atomic_t bgchild_exited = false;
177
179
178
180
/* End position for xlog streaming, empty string if unknown yet */
179
181
static XLogRecPtr xlogendptr ;
@@ -277,6 +279,18 @@ disconnect_atexit(void)
277
279
}
278
280
279
281
#ifndef WIN32
282
+ /*
283
+ * If the bgchild exits prematurely and raises a SIGCHLD signal, we can abort
284
+ * processing rather than wait until the backup has finished and error out at
285
+ * that time. On Windows, we use a background thread which can communicate
286
+ * without the need for a signal handler.
287
+ */
288
+ static void
289
+ sigchld_handler (SIGNAL_ARGS )
290
+ {
291
+ bgchild_exited = true;
292
+ }
293
+
280
294
/*
281
295
* On windows, our background thread dies along with the process. But on
282
296
* Unix, if we have started a subprocess, we want to kill it off so it
@@ -285,7 +299,7 @@ disconnect_atexit(void)
285
299
static void
286
300
kill_bgchild_atexit (void )
287
301
{
288
- if (bgchild > 0 )
302
+ if (bgchild > 0 && ! bgchild_exited )
289
303
kill (bgchild , SIGTERM );
290
304
}
291
305
#endif
@@ -572,17 +586,28 @@ LogStreamerMain(logstreamer_param *param)
572
586
stream .do_sync );
573
587
574
588
if (!ReceiveXlogStream (param -> bgconn , & stream ))
575
-
589
+ {
576
590
/*
577
591
* Any errors will already have been reported in the function process,
578
592
* but we need to tell the parent that we didn't shutdown in a nice
579
593
* way.
580
594
*/
595
+ #ifdef WIN32
596
+ /*
597
+ * In order to signal the main thread of an ungraceful exit we
598
+ * set the same flag that we use on Unix to signal SIGCHLD.
599
+ */
600
+ bgchild_exited = true;
601
+ #endif
581
602
return 1 ;
603
+ }
582
604
583
605
if (!stream .walmethod -> finish ())
584
606
{
585
607
pg_log_error ("could not finish writing WAL files: %m" );
608
+ #ifdef WIN32
609
+ bgchild_exited = true;
610
+ #endif
586
611
return 1 ;
587
612
}
588
613
@@ -1134,6 +1159,12 @@ ReceiveCopyData(PGconn *conn, WriteDataCallback callback,
1134
1159
exit (1 );
1135
1160
}
1136
1161
1162
+ if (bgchild_exited )
1163
+ {
1164
+ pg_log_error ("background process terminated unexpectedly" );
1165
+ exit (1 );
1166
+ }
1167
+
1137
1168
(* callback ) (r , copybuf , callback_data );
1138
1169
1139
1170
PQfreemem (copybuf );
@@ -2882,6 +2913,18 @@ main(int argc, char **argv)
2882
2913
}
2883
2914
atexit (disconnect_atexit );
2884
2915
2916
+ #ifndef WIN32
2917
+ /*
2918
+ * Trap SIGCHLD to be able to handle the WAL stream process exiting. There
2919
+ * is no SIGCHLD on Windows, there we rely on the background thread setting
2920
+ * the signal variable on unexpected but graceful exit. If the WAL stream
2921
+ * thread crashes on Windows it will bring down the entire process as it's
2922
+ * a thread, so there is nothing to catch should that happen. A crash on
2923
+ * UNIX will be caught by the signal handler.
2924
+ */
2925
+ pqsignal (SIGCHLD , sigchld_handler );
2926
+ #endif
2927
+
2885
2928
/*
2886
2929
* Set umask so that directories/files are created with the same
2887
2930
* permissions as directories/files in the source data directory.
0 commit comments