spawn server improvements (#18115)
* spawn server improvements * fixed message
Costa Tsaousis committed
Jul 11, 2024 at 16:52 UTC
788ae9a44d059d2ed66239d248bd791a9a453a0d
8 files changed
+162
-135
src/daemon/main.c
+5
-17
@@ -324,6 +324,8 @@ static bool service_wait_exit(SERVICE_TYPE service, usec_t timeout_ut) {
324
void web_client_cache_destroy(void);
325
326
void netdata_cleanup_and_exit(int ret, const char *action, const char *action_result, const char *action_data) {
327
+ netdata_exit = 1;
328
+
329
watcher_shutdown_begin();
330
331
nd_log_limits_unlimited();
@@ -344,6 +346,9 @@ void netdata_cleanup_and_exit(int ret, const char *action, const char *action_re
346
(void) rename(agent_crash_file, agent_incomplete_shutdown_file);
347
watcher_step_complete(WATCHER_STEP_ID_CREATE_SHUTDOWN_FILE);
348
349
+ netdata_main_spawn_server_cleanup();
350
+ watcher_step_complete(WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER);
351
+
352
#ifdef ENABLE_DBENGINE
353
if(dbengine_enabled) {
354
for (size_t tier = 0; tier < storage_tiers; tier++)
@@ -486,9 +491,6 @@ void netdata_cleanup_and_exit(int ret, const char *action, const char *action_re
491
#endif
492
watcher_step_complete(WATCHER_STEP_ID_FREE_OPENSSL_STRUCTURES);
493
489
- netdata_main_spawn_server_cleanup();
490
- watcher_step_complete(WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER);
491
-
494
(void) unlink(agent_incomplete_shutdown_file);
495
watcher_step_complete(WATCHER_STEP_ID_REMOVE_INCOMPLETE_SHUTDOWN_FILE);
496
@@ -667,8 +669,6 @@ void cancel_main_threads() {
669
}
670
}
671
670
- netdata_exit = 1;
671
-
672
while(found && max > 0) {
673
max -= step;
674
netdata_log_info("Waiting %d threads to finish...", found);
@@ -2179,18 +2179,6 @@ int netdata_main(int argc, char **argv) {
2179
delta_startup_time("initialize registry");
2180
registry_init();
2181
2182
- // fork the spawn server
2183
- delta_startup_time("fork the spawn server");
2184
-
2185
- /*
2186
- * Libuv uv_spawn() uses SIGCHLD internally:
2187
- * https://github.com/libuv/libuv/blob/cc51217a317e96510fbb284721d5e6bc2af31e33/src/unix/process.c#L485
2188
- * and inadvertently replaces the netdata signal handler which was setup during initialization.
2189
- * Thusly, we must explicitly restore the signal handler for SIGCHLD.
2190
- * Warning: extreme care is needed when mixing and matching POSIX and libuv.
2191
- */
2192
- signals_restore_SIGCHLD();
2193
-
2182
// ------------------------------------------------------------------------
2183
// initialize rrd, registry, health, rrdpush, etc.
2184
src/daemon/signals.c
+6
-60
@@ -2,6 +2,12 @@
2
3
#include "common.h"
4
5
+/*
6
+ * IMPORTANT: Libuv uv_spawn() uses SIGCHLD internally:
7
+ * https://github.com/libuv/libuv/blob/cc51217a317e96510fbb284721d5e6bc2af31e33/src/unix/process.c#L485
8
+ * Extreme care is needed when mixing and matching POSIX and libuv.
9
+ */
10
+
11
typedef enum signal_action {
12
NETDATA_SIGNAL_END_OF_LIST,
13
NETDATA_SIGNAL_IGNORE,
@@ -9,7 +15,6 @@ typedef enum signal_action {
15
NETDATA_SIGNAL_REOPEN_LOGS,
16
NETDATA_SIGNAL_RELOAD_HEALTH,
17
NETDATA_SIGNAL_FATAL,
12
- NETDATA_SIGNAL_CHILD,
18
} SIGNAL_ACTION;
19
20
static struct {
@@ -25,7 +30,6 @@ static struct {
30
{ SIGHUP, "SIGHUP", 0, NETDATA_SIGNAL_REOPEN_LOGS },
31
{ SIGUSR2, "SIGUSR2", 0, NETDATA_SIGNAL_RELOAD_HEALTH },
32
{ SIGBUS, "SIGBUS", 0, NETDATA_SIGNAL_FATAL },
28
- { SIGCHLD, "SIGCHLD", 0, NETDATA_SIGNAL_CHILD },
33
34
// terminator
35
{ 0, "NONE", 0, NETDATA_SIGNAL_END_OF_LIST }
@@ -93,18 +97,6 @@ void signals_init(void) {
97
}
98
}
99
96
-void signals_restore_SIGCHLD(void)
97
-{
98
- struct sigaction sa;
99
-
100
- sa.sa_flags = 0;
101
- sigfillset(&sa.sa_mask);
102
- sa.sa_handler = signal_handler;
103
-
104
- if(sigaction(SIGCHLD, &sa, NULL) == -1)
105
- netdata_log_error("SIGNAL: Failed to change signal handler for: SIGCHLD");
106
-}
107
-
100
void signals_reset(void) {
101
struct sigaction sa;
102
sigemptyset(&sa.sa_mask);
@@ -118,48 +110,6 @@ void signals_reset(void) {
110
}
111
}
112
121
-static void sigchild_handle() {
122
- int status;
123
- pid_t pid;
124
-
125
- // Loop to check for exited child processes
126
- while ((pid = waitpid((pid_t)(-1), &status, WNOHANG)) != 0) {
127
- if(pid == -1)
128
- break;
129
-
130
- if(WIFEXITED(status)) {
131
- nd_log(NDLS_DAEMON, NDLP_INFO,
132
- "DAEMON: child with pid %d exited normally with exit code %d",
133
- pid, WEXITSTATUS(status));
134
- }
135
- else if(WIFSIGNALED(status)) {
136
- if(WCOREDUMP(status))
137
- nd_log(NDLS_DAEMON, NDLP_INFO,
138
- "DAEMON: child with pid %d coredump'd due to signal %d",
139
- pid, WTERMSIG(status));
140
- else
141
- nd_log(NDLS_DAEMON, NDLP_INFO,
142
- "DAEMON: child with pid %d killed by signal %d",
143
- pid, WTERMSIG(status));
144
- }
145
- else if(WIFSTOPPED(status)) {
146
- nd_log(NDLS_DAEMON, NDLP_INFO,
147
- "DAEMON: child with pid %d stopped due to signal %d",
148
- pid, WSTOPSIG(status));
149
- }
150
- else if(WIFCONTINUED(status)) {
151
- nd_log(NDLS_DAEMON, NDLP_INFO,
152
- "DAEMON: child with pid %d continued due to signal %d",
153
- pid, SIGCONT);
154
- }
155
- else {
156
- nd_log(NDLS_COLLECTORS, NDLP_INFO,
157
- "DAEMON: child with pid %d reports unhandled status",
158
- pid);
159
- }
160
- }
161
-}
162
-
113
void signals_handle(void) {
114
while(1) {
115
@@ -211,10 +161,6 @@ void signals_handle(void) {
161
fatal("SIGNAL: Received %s. netdata now exits.", name);
162
break;
163
214
- case NETDATA_SIGNAL_CHILD:
215
- sigchild_handle();
216
- break;
217
-
164
default:
165
netdata_log_info("SIGNAL: Received %s. No signal handler configured. Ignoring it.", name);
166
break;
src/daemon/signals.h
-1
@@ -6,7 +6,6 @@
6
void signals_init(void);
7
void signals_block(void);
8
void signals_unblock(void);
9
-void signals_restore_SIGCHLD(void);
9
void signals_reset(void);
10
void signals_handle(void) NORETURN;
11
src/daemon/watcher.c
+3
-2
@@ -65,6 +65,7 @@ void *watcher_main(void *arg)
65
usec_t shutdown_start_time = now_monotonic_usec();
66
67
watcher_wait_for_step(WATCHER_STEP_ID_CREATE_SHUTDOWN_FILE);
68
+ watcher_wait_for_step(WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER);
69
watcher_wait_for_step(WATCHER_STEP_ID_DBENGINE_EXIT_MODE);
70
watcher_wait_for_step(WATCHER_STEP_ID_CLOSE_WEBRTC_CONNECTIONS);
71
watcher_wait_for_step(WATCHER_STEP_ID_DISABLE_MAINTENANCE_NEW_QUERIES_NEW_WEB_REQUESTS_NEW_STREAMING_CONNECTIONS_AND_ACLK);
@@ -105,6 +106,8 @@ void watcher_thread_start() {
106
107
watcher_steps[WATCHER_STEP_ID_CREATE_SHUTDOWN_FILE].msg =
108
"create shutdown file";
109
+ watcher_steps[WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER].msg =
110
+ "destroy main spawn server";
111
watcher_steps[WATCHER_STEP_ID_DBENGINE_EXIT_MODE].msg =
112
"dbengine exit mode";
113
watcher_steps[WATCHER_STEP_ID_CLOSE_WEBRTC_CONNECTIONS].msg =
@@ -151,8 +154,6 @@ void watcher_thread_start() {
154
"remove pid file";
155
watcher_steps[WATCHER_STEP_ID_FREE_OPENSSL_STRUCTURES].msg =
156
"free openssl structures";
154
- watcher_steps[WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER].msg =
155
- "destroy main spawn server";
157
watcher_steps[WATCHER_STEP_ID_REMOVE_INCOMPLETE_SHUTDOWN_FILE].msg =
158
"remove incomplete shutdown file";
159
src/daemon/watcher.h
+1
-1
@@ -7,6 +7,7 @@
7
8
typedef enum {
9
WATCHER_STEP_ID_CREATE_SHUTDOWN_FILE = 0,
10
+ WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER,
11
WATCHER_STEP_ID_DBENGINE_EXIT_MODE,
12
WATCHER_STEP_ID_CLOSE_WEBRTC_CONNECTIONS,
13
WATCHER_STEP_ID_DISABLE_MAINTENANCE_NEW_QUERIES_NEW_WEB_REQUESTS_NEW_STREAMING_CONNECTIONS_AND_ACLK,
@@ -30,7 +31,6 @@ typedef enum {
31
WATCHER_STEP_ID_CLOSE_SQL_DATABASES,
32
WATCHER_STEP_ID_REMOVE_PID_FILE,
33
WATCHER_STEP_ID_FREE_OPENSSL_STRUCTURES,
33
- WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER,
34
WATCHER_STEP_ID_REMOVE_INCOMPLETE_SHUTDOWN_FILE,
35
36
// Always keep this as the last enum value
src/libnetdata/spawn_server/spawn_popen.c
+9
-5
@@ -3,14 +3,14 @@
3
#include "spawn_popen.h"
4
5
SPAWN_SERVER *netdata_main_spawn_server = NULL;
6
+static SPINLOCK netdata_main_spawn_server_spinlock = NETDATA_SPINLOCK_INITIALIZER;
7
8
bool netdata_main_spawn_server_init(const char *name, int argc, const char **argv) {
9
if(netdata_main_spawn_server == NULL) {
9
- static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
10
- spinlock_lock(&spinlock);
10
+ spinlock_lock(&netdata_main_spawn_server_spinlock);
11
if(netdata_main_spawn_server == NULL)
12
netdata_main_spawn_server = spawn_server_create(SPAWN_SERVER_OPTION_EXEC, name, NULL, argc, argv);
13
- spinlock_unlock(&spinlock);
13
+ spinlock_unlock(&netdata_main_spawn_server_spinlock);
14
}
15
16
return netdata_main_spawn_server != NULL;
@@ -18,8 +18,12 @@ bool netdata_main_spawn_server_init(const char *name, int argc, const char **arg
18
19
void netdata_main_spawn_server_cleanup(void) {
20
if(netdata_main_spawn_server) {
21
- spawn_server_destroy(netdata_main_spawn_server);
22
- netdata_main_spawn_server = NULL;
21
+ spinlock_lock(&netdata_main_spawn_server_spinlock);
22
+ if(netdata_main_spawn_server) {
23
+ spawn_server_destroy(netdata_main_spawn_server);
24
+ netdata_main_spawn_server = NULL;
25
+ }
26
+ spinlock_unlock(&netdata_main_spawn_server_spinlock);
27
}
28
}
29
src/libnetdata/spawn_server/spawn_server.c
+137
-49
@@ -471,7 +471,7 @@ static void spawn_server_run_child(SPAWN_SERVER *server, SPAWN_REQUEST *request)
471
// Encoding and decoding of spawn server request argv type of data
472
473
// Function to encode argv or envp
474
-static void* encode_argv(const char **argv, size_t *out_size) {
474
+static void* argv_encode(const char **argv, size_t *out_size) {
475
size_t buffer_size = 1024; // Initial buffer size
476
size_t buffer_used = 0;
477
char *buffer = mallocz(buffer_size);
@@ -505,7 +505,7 @@ static void* encode_argv(const char **argv, size_t *out_size) {
505
}
506
507
// Function to decode argv or envp
508
-static const char** decode_argv(const char *buffer, size_t size) {
508
+static const char** argv_decode(const char *buffer, size_t size) {
509
size_t count = 0;
510
const char *ptr = buffer;
511
while (ptr < buffer + size) {
@@ -529,6 +529,54 @@ static const char** decode_argv(const char *buffer, size_t size) {
529
return argv;
530
}
531
532
+static BUFFER *argv_to_cmdline_buffer(const char **argv) {
533
+ BUFFER *wb = buffer_create(0, NULL);
534
+
535
+ for(size_t i = 0; argv[i] ;i++) {
536
+ const char *s = argv[i];
537
+ size_t len = strlen(s);
538
+ buffer_need_bytes(wb, len * 2 + 1);
539
+
540
+ bool needs_quotes = false;
541
+ for(const char *c = s; !needs_quotes && *c ; c++) {
542
+ switch(*c) {
543
+ case ' ':
544
+ case '\v':
545
+ case '\t':
546
+ case '\n':
547
+ case '"':
548
+ needs_quotes = true;
549
+ break;
550
+
551
+ default:
552
+ break;
553
+ }
554
+ }
555
+
556
+ if(needs_quotes && buffer_strlen(wb))
557
+ buffer_strcat(wb, " \"");
558
+ else
559
+ buffer_putc(wb, ' ');
560
+
561
+ for(const char *c = s; *c ; c++) {
562
+ switch(*c) {
563
+ case '"':
564
+ buffer_putc(wb, '\\');
565
+ // fall through
566
+
567
+ default:
568
+ buffer_putc(wb, *c);
569
+ break;
570
+ }
571
+ }
572
+
573
+ if(needs_quotes)
574
+ buffer_strcat(wb, "\"");
575
+ }
576
+
577
+ return wb;
578
+}
579
+
580
// --------------------------------------------------------------------------------------------------------------------
581
// Sending and receiving requests
582
@@ -600,12 +648,12 @@ static bool spawn_server_send_request(ND_UUID *magic, SPAWN_REQUEST *request) {
648
bool ret = false;
649
650
size_t env_size = 0;
603
- void *encoded_env = encode_argv(request->environment, &env_size);
651
+ void *encoded_env = argv_encode(request->environment, &env_size);
652
if (!encoded_env)
653
goto cleanup;
654
655
size_t argv_size = 0;
608
- void *encoded_argv = encode_argv(request->argv, &argv_size);
656
+ void *encoded_argv = argv_encode(request->argv, &argv_size);
657
if (!encoded_argv)
658
goto cleanup;
659
@@ -684,6 +732,19 @@ cleanup:
732
return ret;
733
}
734
735
+static void request_free(SPAWN_REQUEST *rq) {
736
+ if(rq->fds[0] != -1) close(rq->fds[0]);
737
+ if(rq->fds[1] != -1) close(rq->fds[1]);
738
+ if(rq->fds[2] != -1) close(rq->fds[2]);
739
+ if(rq->fds[3] != -1) close(rq->fds[3]);
740
+ if(rq->socket != -1) close(rq->socket);
741
+ freez((void *)rq->argv);
742
+ freez((void *)rq->environment);
743
+ freez((void *)rq->data);
744
+ freez((void *)rq->cmdline);
745
+ freez((void *)rq);
746
+}
747
+
748
static void spawn_server_receive_request(int sock, SPAWN_SERVER *server) {
749
struct msghdr msg = {0};
750
struct iovec iov[7];
@@ -695,7 +756,7 @@ static void spawn_server_receive_request(int sock, SPAWN_SERVER *server) {
756
ND_UUID magic = UUID_ZERO;
757
SPAWN_INSTANCE_TYPE type;
758
char cmsgbuf[CMSG_SPACE(sizeof(int) * SPAWN_SERVER_TRANSFER_FDS)];
698
- char *envp = NULL, *argv = NULL, *data = NULL;
759
+ char *envp_encoded = NULL, *argv_encoded = NULL, *data = NULL;
760
int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1, custom_fd = -1;
761
762
// First recvmsg() to read sizes and control message
@@ -791,14 +852,13 @@ static void spawn_server_receive_request(int sock, SPAWN_SERVER *server) {
852
nd_log(NDLS_COLLECTORS, NDLP_ERR,
853
"SPAWN SERVER: invalid file descriptors received, stdin = %d, stdout = %d, stderr = %d",
854
stdin_fd, stdout_fd, stderr_fd);
794
- close(sock);
855
goto cleanup;
856
}
857
858
// Second recvmsg() to read buffer contents
799
- iov[0].iov_base = envp = mallocz(env_size);
859
+ iov[0].iov_base = envp_encoded = mallocz(env_size);
860
iov[0].iov_len = env_size;
801
- iov[1].iov_base = argv = mallocz(argv_size);
861
+ iov[1].iov_base = argv_encoded = mallocz(argv_size);
862
iov[1].iov_len = argv_size;
863
iov[2].iov_base = data = mallocz(data_size);
864
iov[2].iov_len = data_size;
@@ -811,15 +871,14 @@ static void spawn_server_receive_request(int sock, SPAWN_SERVER *server) {
871
ssize_t total_bytes_received = recvmsg(sock, &msg, 0);
872
if (total_bytes_received < 0) {
873
nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: failed to recvmsg() the second part of the request.");
814
- close(sock);
874
goto cleanup;
875
}
876
877
// fprintf(stderr, "SPAWN SERVER: received request %zu (fds: %d, %d, %d, %d)\n", request_id,
878
// stdin_fd, stdout_fd, stderr_fd, custom_fd);
879
821
- SPAWN_REQUEST *request = mallocz(sizeof(*request));
822
- *request = (SPAWN_REQUEST){
880
+ SPAWN_REQUEST *rq = mallocz(sizeof(*rq));
881
+ *rq = (SPAWN_REQUEST){
882
.pid = 0,
883
.request_id = request_id,
884
.socket = sock,
@@ -829,50 +888,78 @@ static void spawn_server_receive_request(int sock, SPAWN_SERVER *server) {
888
[2] = stderr_fd,
889
[3] = custom_fd,
890
},
832
- .environment = decode_argv(envp, env_size),
833
- .argv = decode_argv(argv, argv_size),
891
+ .environment = argv_decode(envp_encoded, env_size),
892
+ .argv = argv_decode(argv_encoded, argv_size),
893
.data = data,
894
.data_size = data_size,
895
.type = type
896
};
897
898
+ switch(rq->type) {
899
+ case SPAWN_INSTANCE_TYPE_EXEC:
900
+ if(rq->argv) {
901
+ CLEAN_BUFFER *wb = argv_to_cmdline_buffer(rq->argv);
902
+ rq->cmdline = strdupz(buffer_tostring(wb));
903
+ }
904
+ break;
905
+
906
+ case SPAWN_INSTANCE_TYPE_CALLBACK:
907
+ rq->cmdline = strdupz("callback() function");
908
+ break;
909
+
910
+ default:
911
+ rq->cmdline = strdupz("[unknown request type]");
912
+ break;
913
+ }
914
+
915
pid_t pid = fork();
916
if (pid == 0) {
917
// the child
842
- spawn_server_run_child(server, request);
918
+ spawn_server_run_child(server, rq);
919
exit(63);
920
}
921
else if (pid > 0) {
922
// the parent
847
- request->environment = NULL; // will be free'd at cleanup
848
- request->argv = NULL; // will be free'd at cleanup
849
- request->data = NULL; // will be free'd at cleanup
850
- request->data_size = 0;
851
- request->pid = pid;
852
- request->fds[0] = -1;
853
- request->fds[1] = -1;
854
- request->fds[2] = -1;
855
- request->fds[3] = -1;
856
- DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(spawn_server_requests, request, prev, next);
923
+ rq->pid = pid;
924
+
925
+ // do not keep data we don't need at the parent
926
+ freez(envp_encoded); freez((void *)rq->environment); rq->environment = NULL;
927
+ freez(argv_encoded); freez((void *)rq->argv); rq->argv = NULL;
928
+ freez((void *)rq->data); rq->data = NULL;
929
+ rq->data_size = 0;
930
+
931
+ // do not keep fds we don't need at the parent
932
+ if(rq->fds[0] != -1) { close(rq->fds[0]); rq->fds[0] = -1; }
933
+ if(rq->fds[1] != -1) { close(rq->fds[1]); rq->fds[1] = -1; }
934
+ if(rq->fds[2] != -1) { close(rq->fds[2]); rq->fds[2] = -1; }
935
+ if(rq->fds[3] != -1) { close(rq->fds[3]); rq->fds[3] = -1; }
936
+
937
+ // keep it in the list
938
+ DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(spawn_server_requests, rq, prev, next);
939
940
// do not fork this socket on other children
859
- sock_setcloexec(request->socket);
860
- }
861
- else {
862
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Failed to fork() child.");
863
- spawn_server_send_status_failure(stdout_fd);
864
- // the other allocations (envp, argv, data) will be free'd at cleanup
865
- freez((void *)request);
866
- close(sock);
941
+ sock_setcloexec(rq->socket);
942
+
943
+ // done with this
944
+ return;
945
}
946
947
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Failed to fork() child.");
948
+ spawn_server_send_status_failure(stdout_fd);
949
+ // the other allocations (envp, argv, data) will be free'd at cleanup
950
+ request_free(rq);
951
+ freez(envp_encoded);
952
+ freez(argv_encoded);
953
+ return;
954
+
955
cleanup:
956
+ close(sock);
957
if(stdin_fd != -1) close(stdin_fd);
958
if(stdout_fd != -1) close(stdout_fd);
959
if(stderr_fd != -1) close(stderr_fd);
960
if(custom_fd != -1) close(custom_fd);
874
- freez(envp);
875
- freez(argv);
961
+ freez(envp_encoded);
962
+ freez(argv_encoded);
963
freez(data);
964
}
965
@@ -906,6 +993,8 @@ static void spawn_server_process_sigchld(void) {
993
if(pid == -1)
994
break;
995
996
+ errno_clear();
997
+
998
SPAWN_REQUEST *rq = find_request_by_pid(pid);
999
size_t request_id = rq ? rq->request_id : 0;
1000
bool send_report_remove_request = false;
@@ -913,45 +1002,44 @@ static void spawn_server_process_sigchld(void) {
1002
if(WIFEXITED(status)) {
1003
if(WEXITSTATUS(status))
1004
nd_log(NDLS_COLLECTORS, NDLP_INFO,
916
- "SPAWN SERVER: child with pid %d (request %zu) exited normally with exit code %d",
917
- pid, request_id, WEXITSTATUS(status));
1005
+ "SPAWN SERVER: child with pid %d (request %zu) exited with exit code %d: %s",
1006
+ pid, request_id, WEXITSTATUS(status), rq ? rq->cmdline : "[request not found]");
1007
send_report_remove_request = true;
1008
}
1009
else if(WIFSIGNALED(status)) {
1010
if(WCOREDUMP(status))
1011
nd_log(NDLS_COLLECTORS, NDLP_INFO,
923
- "SPAWN SERVER: child with pid %d (request %zu) coredump'd due to signal %d",
924
- pid, request_id, WTERMSIG(status));
1012
+ "SPAWN SERVER: child with pid %d (request %zu) coredump'd due to signal %d: %s",
1013
+ pid, request_id, WTERMSIG(status), rq ? rq->cmdline : "[request not found]");
1014
else
1015
nd_log(NDLS_COLLECTORS, NDLP_INFO,
927
- "SPAWN SERVER: child with pid %d (request %zu) killed by signal %d",
928
- pid, request_id, WTERMSIG(status));
1016
+ "SPAWN SERVER: child with pid %d (request %zu) killed by signal %d: %s",
1017
+ pid, request_id, WTERMSIG(status), rq ? rq->cmdline : "[request not found]");
1018
send_report_remove_request = true;
1019
}
1020
else if(WIFSTOPPED(status)) {
1021
nd_log(NDLS_COLLECTORS, NDLP_INFO,
933
- "SPAWN SERVER: child with pid %d (request %zu) stopped due to signal %d",
934
- pid, request_id, WSTOPSIG(status));
1022
+ "SPAWN SERVER: child with pid %d (request %zu) stopped due to signal %d: %s",
1023
+ pid, request_id, WSTOPSIG(status), rq ? rq->cmdline : "[request not found]");
1024
send_report_remove_request = false;
1025
}
1026
else if(WIFCONTINUED(status)) {
1027
nd_log(NDLS_COLLECTORS, NDLP_INFO,
939
- "SPAWN SERVER: child with pid %d (request %zu) continued due to signal %d",
940
- pid, request_id, SIGCONT);
1028
+ "SPAWN SERVER: child with pid %d (request %zu) continued due to signal %d: %s",
1029
+ pid, request_id, SIGCONT, rq ? rq->cmdline : "[request not found]");
1030
send_report_remove_request = false;
1031
}
1032
else {
1033
nd_log(NDLS_COLLECTORS, NDLP_INFO,
945
- "SPAWN SERVER: child with pid %d (request %zu) reports unhandled status",
946
- pid, request_id);
1034
+ "SPAWN SERVER: child with pid %d (request %zu) reports unhandled status: %s",
1035
+ pid, request_id, rq ? rq->cmdline : "[request not found]");
1036
send_report_remove_request = false;
1037
}
1038
1039
if(send_report_remove_request && rq) {
1040
spawn_server_send_status_exit(rq->socket, status);
952
- close(rq->socket);
1041
DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(spawn_server_requests, rq, prev, next);
954
- freez(rq);
1042
+ request_free(rq);
1043
}
1044
}
1045
}
@@ -961,7 +1049,7 @@ static void signals_unblock(void) {
1049
sigfillset(&sigset);
1050
1051
if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) {
964
- netdata_log_error("SIGNAL: Could not unblock signals for threads");
1052
+ netdata_log_error("SPAWN SERVER: Could not unblock signals for threads");
1053
}
1054
}
1055
src/libnetdata/spawn_server/spawn_server.h
+1
@@ -22,6 +22,7 @@ typedef enum __attribute__((packed)) {
22
// this is only used publicly for SPAWN_INSTANCE_TYPE_CALLBACK
23
// which is not available in Windows
24
typedef struct spawn_request {
25
+ const char *cmdline;
26
size_t request_id;
27
pid_t pid;
28
int socket;