diff options
author | 2017-12-18 14:21:33 -0600 | |
---|---|---|
committer | 2017-12-18 14:21:33 -0600 | |
commit | 0b39d16ac61b0a483617c1c99b76d06835fc82b4 (patch) | |
tree | 033a189624edeec54e776128201093b1d0c93edd | |
parent | b6b68db896f9963558334aff7fca61adde4ec10f (diff) | |
download | pseudo-0b39d16ac61b0a483617c1c99b76d06835fc82b4.tar.gz pseudo-0b39d16ac61b0a483617c1c99b76d06835fc82b4.tar.bz2 pseudo-0b39d16ac61b0a483617c1c99b76d06835fc82b4.zip |
Print list of clients on SIGUSR2
This patch relates to some debugging of handling of large numbers
of clients, but actually it seems useful to have, so checking
it in.
Signed-off-by: Seebs <seebs@seebs.net>
-rw-r--r-- | ChangeLog.txt | 4 | ||||
-rw-r--r-- | pseudo_server.c | 32 |
2 files changed, 36 insertions, 0 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 8ba1ffa..888334a 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +2017-12-18: + * (seebs) Add a list of clients as a handler for SIGUSR2. (Useful + for debugging, maybe.) + 2017-04-13: * (seebs) don't unset LD_PRELOAD or the like, because if you do that, bash can segfault because it "knows" how many diff --git a/pseudo_server.c b/pseudo_server.c index 7c2db2f..68433b3 100644 --- a/pseudo_server.c +++ b/pseudo_server.c @@ -62,6 +62,7 @@ static int active_clients = 0, highest_client = 0, max_clients = 0; int pseudo_server_timeout = DEFAULT_PSEUDO_SERVER_TIMEOUT; static int die_peacefully = 0; static int die_forcefully = 0; +static sig_atomic_t do_list_clients = 0; /* when the client is linked with pseudo_wrappers, these are defined there. * when it is linked with pseudo_server, though, we have to provide different @@ -77,6 +78,11 @@ quit_now(int signal) { die_forcefully = 1; } +static void +set_do_list_clients(int sig) { + do_list_clients = sig; +} + static int messages = 0, responses = 0; static struct timeval message_time = { .tv_sec = 0 }; @@ -581,9 +587,14 @@ pseudo_server_loop(void) { int rc; int fd; int loop_timeout = pseudo_server_timeout; + struct sigaction eat_usr2 = { + .sa_handler = set_do_list_clients + }; clients = malloc(16 * sizeof(*clients)); + sigaction(SIGUSR2, &eat_usr2, NULL); + clients[0].fd = listen_fd; clients[0].pid = getpid(); @@ -616,7 +627,12 @@ pseudo_server_loop(void) { /* EINTR tends to come from profiling, so it is not a good reason to * exit; other signals are caught and set the flag causing a graceful * exit. */ + sigset_t maskusr2; + sigemptyset(&maskusr2); + sigaddset(&maskusr2, SIGUSR2); + sigprocmask(SIG_BLOCK, &maskusr2, NULL); while ((rc = select(max_fd + 1, &reads, &writes, &events, &timeout)) >= 0 || (errno == EINTR)) { + sigprocmask(SIG_UNBLOCK, &maskusr2, NULL); if (rc == 0 || (rc == -1 && errno == EINTR)) { /* If there's no clients, start timing out. If there * are active clients, never time out. @@ -692,6 +708,21 @@ pseudo_server_loop(void) { } pseudo_debug(PDBGF_SERVER, "server loop complete [%d clients left]\n", active_clients); } + if (do_list_clients) { + do_list_clients = 0; + pseudo_diag("listing clients [1 through %d]:\n", highest_client); + for (i = 1; i <= highest_client; ++i) { + if (clients[i].fd == -1) { + pseudo_diag("client %4d: inactive.\n", i); + continue; + } + pseudo_diag("client %4d: fd %4d, pid %5d, state %s, program %s\n", + i, clients[i].fd, clients[i].pid, + FD_ISSET(clients[i].fd, &reads) ? "R" : "-", + clients[i].program ? clients[i].program : "<unspecified>"); + } + pseudo_diag("done.\n"); + } if (die_peacefully || die_forcefully) { pseudo_debug(PDBGF_SERVER, "quitting.\n"); pseudo_debug(PDBGF_SERVER | PDBGF_BENCHMARK, "server %d exiting: handled %d messages in %.4f seconds\n", @@ -735,6 +766,7 @@ pseudo_server_loop(void) { } /* reinitialize timeout because Linux select alters it */ timeout = (struct timeval) { .tv_sec = LOOP_DELAY, .tv_usec = 0 }; + sigprocmask(SIG_BLOCK, &maskusr2, NULL); } pseudo_diag("select failed: %s\n", strerror(errno)); } |