diff options
author | Clark Williams <williams@redhat.com> | 2011-05-05 13:44:09 -0500 |
---|---|---|
committer | Clark Williams <williams@redhat.com> | 2011-05-05 13:44:09 -0500 |
commit | 809f870eb8c0bac98f80eaca04f4ea55d094a14f (patch) | |
tree | e7cec7d3e7f27115030c42f522c08b9f813bf5d1 | |
parent | 02da29f4508f18b760af4d163b4a92ee90106152 (diff) | |
download | rt-tests-809f870eb8c0bac98f80eaca04f4ea55d094a14f.tar.gz rt-tests-809f870eb8c0bac98f80eaca04f4ea55d094a14f.tar.xz |
hackbench: add setjmp/longjmp and rework signal handling logic
Use setjmp/longjump to get the parent process back out of processing
loop and into forced kill mode for the child processes/threads.
Added function reset_worker_signals() so that workers (sender and
receiver) don't try to reap as well.
Signed-off-by: Clark Williams <williams@redhat.com>
-rw-r--r-- | src/hackbench/hackbench.c | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/src/hackbench/hackbench.c b/src/hackbench/hackbench.c index c8d12bd..03b74b0 100644 --- a/src/hackbench/hackbench.c +++ b/src/hackbench/hackbench.c @@ -27,6 +27,7 @@ #include <limits.h> #include <getopt.h> #include <signal.h> +#include <setjmp.h> static unsigned int datasize = 100; static unsigned int loops = 100; @@ -65,6 +66,8 @@ childinfo_t *child_tab = NULL; unsigned int total_children = 0; unsigned int signal_caught = 0; +static jmp_buf jmpbuf; + inline static void sneeze(const char *msg) { /* Avoid calling these functions when called from a code path * which involves sigcatcher(), as they are not reentrant safe. @@ -115,12 +118,19 @@ static void ready(int ready_out, int wakefd) barf("poll"); } +static void reset_worker_signals(void) +{ + signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); +} + /* Sender sprays loops messages down each file descriptor */ static void *sender(struct sender_context *ctx) { char data[datasize]; unsigned int i, j; + reset_worker_signals(); ready(ctx->ready_out, ctx->wakefd); memset(&data, '-', datasize); @@ -148,6 +158,7 @@ static void *receiver(struct receiver_context* ctx) { unsigned int i; + reset_worker_signals(); if (process_mode) close(ctx->in_fds[1]); @@ -226,21 +237,24 @@ unsigned int reap_workers(childinfo_t *child, unsigned int totchld, unsigned int int status, err; void *thr_status; + if (dokill) { + fprintf(stderr, "sending SIGTERM to all child processes\n"); + signal(SIGTERM, SIG_IGN); + kill(0, SIGTERM); + } + for( i = 0; i < totchld; i++ ) { + int pid; switch( process_mode ) { case 1: /* process mode */ - if( dokill ) { - kill(child[i].pid, SIGTERM); - } fflush(stdout); - waitpid(child[i].pid, &status, 0); + pid = wait(&status); + if (pid == -1 && errno == ECHILD) + break; if (!WIFEXITED(status)) rc++; break; case 0: /* threaded mode */ - if( dokill ) { - pthread_kill(child[i].threadid, SIGTERM); - } err = pthread_join(child[i].threadid, &thr_status); if( err != 0 ) { sneeze("pthread_join()"); @@ -398,11 +412,9 @@ static void process_options (int argc, char *argv[]) void sigcatcher(int sig) { /* All caught signals will cause the program to exit */ signal_caught = 1; - if( child_tab && (total_children > 0) ) { - reap_workers(child_tab, total_children, 1); - } - fprintf(stderr, "** Operation aborted **\n"); - exit(0); + fprintf(stderr, "Signal %d caught, longjmp'ing out!\n", sig); + signal(sig, SIG_IGN); + longjmp(jmpbuf, 1); } int main(int argc, char *argv[]) @@ -432,34 +444,37 @@ int main(int argc, char *argv[]) signal(SIGTERM, sigcatcher); signal(SIGHUP, SIG_IGN); - total_children = 0; - for (i = 0; i < num_groups; i++) { - int c = group(child_tab, total_children, num_fds, readyfds[1], wakefds[0]); - if( c != (num_fds*2) ) { - fprintf(stderr, "%i children started. Expected %i\n", c, num_fds*2); - reap_workers(child_tab, total_children + c, 1); - barf("Creating workers"); + if (setjmp(jmpbuf) == 0) { + total_children = 0; + for (i = 0; i < num_groups; i++) { + int c = group(child_tab, total_children, num_fds, readyfds[1], wakefds[0]); + if( c != (num_fds*2) ) { + fprintf(stderr, "%i children started. Expected %i\n", c, num_fds*2); + reap_workers(child_tab, total_children + c, 1); + barf("Creating workers"); + } + total_children += c; } - total_children += c; - } - - /* Wait for everyone to be ready */ - for (i = 0; i < total_children; i++) - if (read(readyfds[0], &dummy, 1) != 1) { + /* Wait for everyone to be ready */ + for (i = 0; i < total_children; i++) + if (read(readyfds[0], &dummy, 1) != 1) { + reap_workers(child_tab, total_children, 1); + barf("Reading for readyfds"); + } + + gettimeofday(&start, NULL); + + /* Kick them off */ + if (write(wakefds[1], &dummy, 1) != 1) { reap_workers(child_tab, total_children, 1); - barf("Reading for readyfds"); + barf("Writing to start senders"); } - - gettimeofday(&start, NULL); - - /* Kick them off */ - if (write(wakefds[1], &dummy, 1) != 1) { - reap_workers(child_tab, total_children, 1); - barf("Writing to start senders"); } + else + fprintf(stderr, "longjmp'ed out, reaping children\n"); /* Reap them all */ - reap_workers(child_tab, total_children, 0); + reap_workers(child_tab, total_children, signal_caught); gettimeofday(&stop, NULL); |