diff options
author | hunt <hunt> | 2005-07-08 19:23:33 +0000 |
---|---|---|
committer | hunt <hunt> | 2005-07-08 19:23:33 +0000 |
commit | d533bbb2258a1cb094eb950ff25ee985d5f11715 (patch) | |
tree | 8d9ef12b6024601c6afa3bf2cacaa4152d9af573 /runtime/stpd/librelay.c | |
parent | 85365d1b9cfd2d75cb847be4ced3de583f91865b (diff) | |
download | systemtap-steved-d533bbb2258a1cb094eb950ff25ee985d5f11715.tar.gz systemtap-steved-d533bbb2258a1cb094eb950ff25ee985d5f11715.tar.xz systemtap-steved-d533bbb2258a1cb094eb950ff25ee985d5f11715.zip |
2005-07-08 Martin Hunt <hunt@redhat.com>
* librelay.c (sigchld): Signal handler to detect
completion of module loading.
(init_stp): Use fork/exec instead of system() so
we can get async signal of module load success/failure.
(cleanup_and_exit): New function.
(sigproc): If module is not loaded, don't send message to it.
(stp_main_loop): Call cleanup_and_exit() when STP_EXIT
is received. Don't send a request for the transport
mode. The module will send notification to the daemon
when it is ready.
* stpd.c (main): Don't print message until module
is loaded.
Diffstat (limited to 'runtime/stpd/librelay.c')
-rw-r--r-- | runtime/stpd/librelay.c | 131 |
1 files changed, 82 insertions, 49 deletions
diff --git a/runtime/stpd/librelay.c b/runtime/stpd/librelay.c index e6823af1..5fdf5e12 100644 --- a/runtime/stpd/librelay.c +++ b/runtime/stpd/librelay.c @@ -43,7 +43,7 @@ /* maximum number of CPUs we can handle - change if more */ #define NR_CPUS 256 - /* relayfs parameters */ +/* relayfs parameters */ static struct params { unsigned subbuf_size; @@ -151,8 +151,8 @@ int send_request(int type, void *data, int len) req = (struct nlmsghdr *)malloc(NLMSG_SPACE(len)); if (req == 0) { - fprintf(stderr, "WARNING: send_request malloc failed\n"); - return -1; + fprintf(stderr, "WARNING: send_request malloc failed\n"); + return -1; } memset(req, 0, NLMSG_SPACE(len)); req->nlmsg_len = NLMSG_LENGTH(len); @@ -160,7 +160,6 @@ int send_request(int type, void *data, int len) req->nlmsg_flags = NLM_F_REQUEST; req->nlmsg_pid = getpid(); memcpy(NLMSG_DATA(req), data, len); - err = send(control_channel, req, req->nlmsg_len, MSG_DONTWAIT); return err; } @@ -197,7 +196,7 @@ static void summarize(void) { int i; - if (streaming()) + if (transport_mode != STP_TRANSPORT_RELAYFS) return; printf("summary:\n"); @@ -450,6 +449,24 @@ err: return -1; } +#include <sys/wait.h> +static void cleanup_and_exit (char *mod_name); +static int module_loaded = 0; +static void sigchld(int signum) +{ + int status; + pid_t pid = wait(&status); + if (pid > 0 && WIFEXITED(status) && WEXITSTATUS(status)) + cleanup_and_exit(""); + signal(SIGCHLD, SIG_DFL); + module_loaded = 1; + + if (quiet) + printf("Logging... Press Control-C to stop.\n"); + else + printf("Press Control-C to stop.\n"); +} + /** * init_stp - initialize the app * @modname: the name of the stp module to load @@ -464,17 +481,25 @@ int init_stp(const char *modname, { int daemon_pid; char buf[1024]; + pid_t pid; ncpus = sysconf(_SC_NPROCESSORS_ONLN); print_totals = print_summary; daemon_pid = getpid(); - sprintf(buf, "insmod %s pid=%d", modname, daemon_pid); - if (system(buf)) { - fprintf(stderr, "ERROR, couldn't insmod probe module %s\n", modname); - return -1; - } + sprintf(buf, "_stp_pid=%d", daemon_pid); + signal(SIGCHLD, sigchld); + + if ((pid = vfork()) < 0) { + perror ("vfork"); + exit(-1); + } else if (pid == 0) { + execl("/sbin/insmod", "insmod", modname, buf, 0); + perror ("exec"); + exit(-1); + } + control_channel = open_control_channel(); if (control_channel < 0) return -1; @@ -518,7 +543,7 @@ static int merge_output(void) ofp = fopen (outfile_name, "w"); if (!ofp) { fprintf (stderr, "ERROR: couldn't open output file %s: errcode = %s\n", - outfile_name, strerror(errno)); + outfile_name, strerror(errno)); return -1; } @@ -537,9 +562,9 @@ static int merge_output(void) if (c == 0 || c == EOF) break; if (!quiet) - fputc_unlocked (c, stdout); + fputc_unlocked (c, stdout); if (!print_only) - fputc_unlocked (c, ofp); + fputc_unlocked (c, ofp); } if (min && ++count != min) { // fprintf(stderr, "got %ld. expected %ld\n", min, count); @@ -562,7 +587,7 @@ static int merge_output(void) fclose (fp[i]); fclose (ofp); if (dropped) - printf ("\033[33mSequence had %d drops.\033[0m\n", dropped); + printf ("\033[33mSequence had %d drops.\033[0m\n", dropped); return 0; } @@ -574,10 +599,10 @@ static void postprocess_and_exit(void) if (print_totals) summarize(); - if (!streaming() && merge) { + if (transport_mode == STP_TRANSPORT_RELAYFS && merge) { close_all_relayfs_files(); merge_output(); - //delete_percpu_files(); + delete_percpu_files(); } close(control_channel); @@ -585,10 +610,48 @@ static void postprocess_and_exit(void) exit(0); } +static void cleanup_and_exit (char *mod_name) +{ + char tmpbuf[128]; + + if (exiting) + return; + + exiting = 1; + + if (transport_mode == STP_TRANSPORT_RELAYFS) { + kill_percpu_threads(ncpus); + if (request_last_buffers() < 0) + exit(1); + } + + if (mod_name && *mod_name) { + /* FIXME. overflow check */ + strcpy (tmpbuf, "/sbin/rmmod "); + strcpy (tmpbuf + strlen(tmpbuf), mod_name); + if (system(tmpbuf)) { + fprintf(stderr, "ERROR: couldn't rmmod probe module %s. No output will be written.\n", + mod_name); + close_all_relayfs_files(); + delete_percpu_files(); + exit(1); + } + + if ( transport_mode == STP_TRANSPORT_RELAYFS && final_cpus_processed < ncpus) + return; + } + postprocess_and_exit(); +} + static void sigproc(int signum) { - while (send_request(STP_EXIT, NULL, 0) < 0) { - usleep (10000); + if (transport_mode && module_loaded) { + int trylimit = 50; + while (send_request(STP_EXIT, NULL, 0) < 0 && trylimit--) + usleep (10000); + } else { + close(control_channel); + exit(0); } } @@ -602,14 +665,10 @@ int stp_main_loop(void) struct transport_msg *transport_msg; unsigned short *ptr; unsigned subbufs_consumed; - char tmpbuf[128]; signal(SIGINT, sigproc); signal(SIGTERM, sigproc); - send_request(STP_TRANSPORT_MODE, &transport_mode, - sizeof(transport_mode)); - while (1) { /* handle messages from control channel */ nb = recv(control_channel, recvbuf, sizeof(recvbuf), 0); struct nlmsghdr *nlh = (struct nlmsghdr *)recvbuf; @@ -668,35 +727,9 @@ int stp_main_loop(void) fputs ((char *)ptr, stdout); break; case STP_EXIT: - if (exiting) - break; - - exiting = 1; - - if (!streaming()) { - kill_percpu_threads(ncpus); - if (request_last_buffers() < 0) - exit(1); - } /* module asks us to unload it and exit */ ptr = NLMSG_DATA(nlh); - /* FIXME. overflow check */ - strcpy (tmpbuf, "/sbin/rmmod "); - strcpy (tmpbuf + strlen(tmpbuf), (char *)ptr); -#if 0 - printf ("Executing \"system %s\"\n", tmpbuf); -#endif - if (system(tmpbuf)) { - fprintf(stderr, "ERROR: couldn't rmmod probe module %s. No output will be written.\n", - (char *)ptr); - close_all_relayfs_files(); - delete_percpu_files(); - exit(1); - } - if (!streaming() && (final_cpus_processed < ncpus)) - break; - - postprocess_and_exit(); + cleanup_and_exit((char *)ptr); break; default: fprintf(stderr, "WARNING: ignored netlink message of type %d\n", (nlh->nlmsg_type)); |