Skip to content

Commit 5942b10

Browse files
committed
WIP: Implement on-reload hooks to reload configuration on SIGHUP.
The configuration is written to file and can be edited with the new command pgcopydb config set; now this command also signals the running process with SIGHUP and the config file can be read and applied on-the-fly.
1 parent fdf33ad commit 5942b10

File tree

12 files changed

+238
-58
lines changed

12 files changed

+238
-58
lines changed

src/bin/pgcopydb/cli_clone_follow.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <errno.h>
88
#include <getopt.h>
99
#include <inttypes.h>
10+
#include <signal.h>
1011
#include <sys/wait.h>
1112
#include <unistd.h>
1213

@@ -20,6 +21,7 @@
2021
#include "parsing_utils.h"
2122
#include "pgsql.h"
2223
#include "progress.h"
24+
#include "signals.h"
2325
#include "string_utils.h"
2426
#include "summary.h"
2527

@@ -171,7 +173,7 @@ cli_clone(int argc, char **argv)
171173
}
172174

173175
/* make sure all sub-processes are now finished */
174-
success = success && copydb_wait_for_subprocesses(copySpecs.failFast);
176+
success = success && copydb_wait_for_subprocesses(copySpecs.failFast, NULL);
175177

176178
if (!success)
177179
{
@@ -307,7 +309,7 @@ clone_and_follow(CopyDataSpec *copySpecs)
307309
}
308310

309311
/* make sure all sub-processes are now finished */
310-
success = success && copydb_wait_for_subprocesses(copySpecs->failFast);
312+
success = success && copydb_wait_for_subprocesses(copySpecs->failFast, NULL);
311313

312314
if (!success)
313315
{
@@ -672,8 +674,8 @@ start_follow_process(CopyDataSpec *copySpecs, StreamSpecs *streamSpecs,
672674

673675

674676
/*
675-
* cli_clone_follow_wait_subprocesses waits until both sub-processes are
676-
* finished.
677+
* cli_clone_follow_wait_subprocesses waits until given sub-processes has
678+
* terminated, and return success when its return code was zero.
677679
*/
678680
static bool
679681
cli_clone_follow_wait_subprocess(const char *name, pid_t pid)
@@ -689,6 +691,21 @@ cli_clone_follow_wait_subprocess(const char *name, pid_t pid)
689691

690692
while (!exited)
691693
{
694+
if (asked_to_reload)
695+
{
696+
log_warn("SIGHUP!");
697+
698+
/*
699+
* Forward the signal to all the sub-processes.
700+
*
701+
* Ignore errors and continue looping anyway, it just means we
702+
* failed to answer to the SIGHUP signal this once time.
703+
*/
704+
(void) signal_process_group(SIGHUP);
705+
706+
asked_to_reload = 0;
707+
}
708+
692709
if (!follow_wait_pid(pid, &exited, &returnCode))
693710
{
694711
/* errors have already been logged */

src/bin/pgcopydb/cli_config.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <errno.h>
88
#include <getopt.h>
99
#include <inttypes.h>
10+
#include <signal.h>
1011

1112
#include "cli_common.h"
1213
#include "cli_root.h"
@@ -15,6 +16,7 @@
1516
#include "commandline.h"
1617
#include "env_utils.h"
1718
#include "log.h"
19+
#include "pidfile.h"
1820
#include "parsing_utils.h"
1921
#include "string_utils.h"
2022

@@ -368,14 +370,40 @@ cli_config_set(int argc, char **argv)
368370
}
369371

370372
/* now read the value from just written file */
371-
if (config_get_setting(&config, cfname, argv[0], value, BUFSIZE))
373+
if (!config_get_setting(&config, cfname, argv[0], value, BUFSIZE))
372374
{
373-
fformat(stdout, "%s\n", value);
375+
log_error("Failed to lookup option %s", argv[0]);
376+
exit(EXIT_CODE_BAD_ARGS);
377+
}
378+
379+
/* now signal the pgcopydb process to reload config (SIGHUP) */
380+
if (file_exists(copySpecs.cfPaths.pidfile))
381+
{
382+
pid_t pid;
383+
384+
log_debug("Reading pidfile \"%s\"", copySpecs.cfPaths.pidfile);
385+
386+
if (!read_pidfile(copySpecs.cfPaths.pidfile, &pid))
387+
{
388+
exit(EXIT_CODE_INTERNAL_ERROR);
389+
}
390+
391+
log_notice("Signaling process %d with SIGHUP", pid);
392+
393+
if (kill(pid, SIGHUP) != 0)
394+
{
395+
log_error("Failed to send SIGHUP signal to process %d: %m", pid);
396+
exit(EXIT_CODE_INTERNAL_ERROR);
397+
}
374398
}
375399
else
376400
{
377-
log_error("Failed to lookup option %s", argv[0]);
378-
exit(EXIT_CODE_BAD_ARGS);
401+
log_error("Failed to send SIGHUP: pidfile does not exists: \"%s\"",
402+
copySpecs.cfPaths.pidfile);
403+
exit(EXIT_CODE_INTERNAL_ERROR);
379404
}
405+
406+
/* finally output the value we just set and signaled */
407+
fformat(stdout, "%s\n", value);
380408
}
381409
}

src/bin/pgcopydb/cli_ping.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ cli_ping(int argc, char **argv)
285285
*/
286286
bool failFast = false;
287287

288-
if (!copydb_wait_for_subprocesses(failFast))
288+
if (!copydb_wait_for_subprocesses(failFast, NULL))
289289
{
290290
/* errors have already been logged */
291291
exit(EXIT_CODE_INTERNAL_ERROR);

src/bin/pgcopydb/copydb.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ copydb_fatal_exit()
968968
* non-zero return code.
969969
*/
970970
bool failFast = false;
971-
return copydb_wait_for_subprocesses(failFast);
971+
return copydb_wait_for_subprocesses(failFast, NULL);
972972
}
973973

974974

@@ -978,18 +978,30 @@ copydb_fatal_exit()
978978
* returns true only when all the subprocesses have returned zero (success).
979979
*/
980980
bool
981-
copydb_wait_for_subprocesses(bool failFast)
981+
copydb_wait_for_subprocesses(bool failFast, OnReloadHook *onReloadHook)
982982
{
983983
bool allReturnCodeAreZero = true;
984984
log_debug("Waiting for sub-processes to finish");
985985

986986
for (;;)
987987
{
988-
int status;
989-
990988
/* ignore errors */
989+
int status;
991990
pid_t pid = waitpid(-1, &status, WNOHANG);
992991

992+
if (asked_to_reload)
993+
{
994+
log_warn("SIGHUP!");
995+
996+
/* call the reload hook when defined */
997+
if (onReloadHook != NULL)
998+
{
999+
(void) (onReloadHook->fun)(onReloadHook->specs);
1000+
}
1001+
1002+
asked_to_reload = 0;
1003+
}
1004+
9931005
switch (pid)
9941006
{
9951007
case -1:

src/bin/pgcopydb/copydb.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ typedef enum
281281
} PostgresDumpSection;
282282

283283

284+
/* on-reload hooks */
285+
typedef void (*reloadHook) (CopyDataSpec *specs);
286+
287+
typedef struct OnReloadHook
288+
{
289+
CopyDataSpec *specs;
290+
reloadHook fun;
291+
} OnReloadHook;
292+
284293
extern GUC srcSettings95[];
285294
extern GUC srcSettings[];
286295
extern GUC dstSettings[];
@@ -329,7 +338,7 @@ bool copydb_init_tablepaths_for_part(CopyFilePaths *cfPaths,
329338
bool copydb_export_snapshot(TransactionSnapshot *snapshot);
330339

331340
bool copydb_fatal_exit(void);
332-
bool copydb_wait_for_subprocesses(bool failFast);
341+
bool copydb_wait_for_subprocesses(bool failFast, OnReloadHook *onReloadHook);
333342

334343
bool copydb_register_sysv_semaphore(SysVResArray *array, Semaphore *semaphore);
335344
bool copydb_register_sysv_queue(SysVResArray *array, Queue *queue);

src/bin/pgcopydb/follow.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,12 @@ follow_wait_subprocesses(StreamSpecs *specs)
736736
}
737737
}
738738

739+
if (asked_to_reload)
740+
{
741+
log_warn("SIGHUP!");
742+
asked_to_reload = 0;
743+
}
744+
739745
/* re-init stillRunning at each iteration */
740746
stillRunning = count;
741747

src/bin/pgcopydb/indexes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ copydb_start_index_processes(CopyDataSpec *specs,
591591
}
592592
}
593593

594-
bool success = copydb_wait_for_subprocesses(specs->failFast);
594+
bool success = copydb_wait_for_subprocesses(specs->failFast, NULL);
595595

596596
/* and write that we successfully finished copying all tables */
597597
if (!write_file("", 0, specs->cfPaths.done.indexes))

src/bin/pgcopydb/main.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ main(int argc, char **argv)
5353
* setpgrp and it has no effect when the calling process is a session
5454
* leader.
5555
*/
56-
setpgrp();
56+
if (setpgid(0, 0) != 0)
57+
{
58+
log_fatal("Failed to set process group: %m");
59+
exit(EXIT_CODE_INTERNAL_ERROR);
60+
}
5761

5862
CommandLine command = root;
5963

src/bin/pgcopydb/pidfile.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ create_pidfile(const char *pidfile, pid_t pid)
3939
{
4040
PQExpBuffer content = createPQExpBuffer();
4141

42-
43-
log_trace("create_pidfile(%d): \"%s\"", pid, pidfile);
42+
log_notice("Creating pidfile for %d at \"%s\"", pid, pidfile);
4443

4544
if (content == NULL)
4645
{

src/bin/pgcopydb/signals.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,30 @@ signal_to_string(int signal)
268268
return "unknown signal";
269269
}
270270
}
271+
272+
273+
/*
274+
* signal_forward_to_pgroup forwards given signal to our process group.
275+
*/
276+
bool
277+
signal_process_group(int sig)
278+
{
279+
pid_t pid = getpid();
280+
pid_t pgrp = getpgid(pid);
281+
282+
if (pgrp == -1)
283+
{
284+
/* continue looping anyway, ignore SIGHUP this time */
285+
log_error("Failed to retrieve process group: %m");
286+
log_error("Failed to process SIGHUP, see above for details");
287+
return false;
288+
}
289+
290+
if (killpg(pgrp, SIGHUP) != 0)
291+
{
292+
log_error("Failed to send SIGHUP signal to process group: %m");
293+
return false;
294+
}
295+
296+
return true;
297+
}

0 commit comments

Comments
 (0)