From 86a65fdbbfe799d8a31d1fcfa6774ce9366054d4 Mon Sep 17 00:00:00 2001 From: compudj Date: Thu, 15 Sep 2005 16:38:31 +0000 Subject: [PATCH] make lttctl and lttd interaction more standard : real daemon git-svn-id: http://ltt.polymtl.ca/svn@1196 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/configure.in | 3 + ltt/branches/poly/lttctl/Makefile.am | 2 + ltt/branches/poly/lttctl/lttctl.c | 45 +++-- ltt/branches/poly/lttd/lttd.c | 10 +- .../modules/gui/tracecontrol/tracecontrol.c | 182 +++++++++++++----- 5 files changed, 166 insertions(+), 76 deletions(-) diff --git a/ltt/branches/poly/configure.in b/ltt/branches/poly/configure.in index ff00a4cd..62db1a53 100644 --- a/ltt/branches/poly/configure.in +++ b/ltt/branches/poly/configure.in @@ -40,6 +40,8 @@ AC_PROG_CC AC_CHECK_LIB([popt], [poptGetNextOpt], POPT_LIBS="-lpopt",AC_MSG_ERROR([libpopt is required in order to compile LinuxTraceToolkit]) ) #AC_CHECK_LIB([m], [round], M_LIBS="-lm",AC_MSG_ERROR([Mathematical libraries are missing.]) ) +AC_CHECK_LIB([util], [forkpty], UTIL_LIBS="-lutil", AC_MSG_ERROR([libutil is +required in order to compile LinuxTraceToolkit])) # Checks for header files. AC_HEADER_STDC @@ -90,6 +92,7 @@ lttvwindowincludedir="${includedir}/lttvwindow" AC_SUBST(POPT_LIBS) +AC_SUBST(UTIL_LIBS) AC_SUBST(lttvlibdir) AC_SUBST(lttvplugindir) AC_SUBST(lttlibdir) diff --git a/ltt/branches/poly/lttctl/Makefile.am b/ltt/branches/poly/lttctl/Makefile.am index 7530c9db..cb33cb41 100644 --- a/ltt/branches/poly/lttctl/Makefile.am +++ b/ltt/branches/poly/lttctl/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to produce Makefile.in +AM_CFLAGS = -DPACKAGE_DATA_DIR=\""$(datadir)"\" -DPACKAGE_BIN_DIR=\""$(bindir)"\" + bin_PROGRAMS = lttctl lttctl_SOURCES = \ diff --git a/ltt/branches/poly/lttctl/lttctl.c b/ltt/branches/poly/lttctl/lttctl.c index fe4be9b1..19605c2e 100644 --- a/ltt/branches/poly/lttctl/lttctl.c +++ b/ltt/branches/poly/lttctl/lttctl.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -47,12 +48,12 @@ static enum trace_ctl_op op = CTL_OP_NONE; static char *channel_root = NULL; static char *trace_root = NULL; -static int sigio_received = 0; +static int sigchld_received = 0; -void handler(int signo) +void sigchld_handler(int signo) { printf("signal %d received\n", signo); - sigio_received = 1; + sigchld_received = 1; } @@ -272,7 +273,7 @@ int create_eventdefs(void) struct dirent *entry; char *facilities_path = getenv("LTT_FACILITIES"); if(facilities_path == NULL) facilities_path = - "/usr/share/LinuxTraceToolkitViewer/facilities"; + PACKAGE_DATA_DIR "/" PACKAGE "/facilities"; ret = mkdir(trace_root, S_IRWXU|S_IRWXG|S_IRWXO); if(ret == -1 && errno != EEXIST) { @@ -295,6 +296,12 @@ int create_eventdefs(void) DIR *facilities_dir = opendir(facilities_path); + if(facilities_dir == NULL) { + perror("Cannot open facilities directory"); + ret = -1; + goto error; + } + while((entry = readdir(facilities_dir)) != NULL) { if(entry->d_name[0] == '.') continue; @@ -342,7 +349,7 @@ close_dest: closedir(facilities_dir); - error: +error: return ret; } @@ -356,7 +363,8 @@ int lttctl_daemon(struct lttctl_handle *handle, char *trace_name) char *lttd_path = getenv("LTT_DAEMON"); struct sigaction act; - if(lttd_path == NULL) lttd_path = "lttd"; + if(lttd_path == NULL) lttd_path = + PACKAGE_BIN_DIR "/lttd"; strcat(channel_path, channel_root); strcat(channel_path, "/"); @@ -366,29 +374,33 @@ int lttctl_daemon(struct lttctl_handle *handle, char *trace_name) ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, n_subbufs); if(ret != 0) goto create_error; - act.sa_handler = handler; + act.sa_handler = sigchld_handler; sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGIO); - sigaction(SIGIO, &act, NULL); - - sigio_received = 0; + sigaddset(&(act.sa_mask), SIGCHLD); + sigaction(SIGCHLD, &act, NULL); pid = fork(); if(pid > 0) { + int status; /* parent */ - while(!sigio_received) pause(); + while(!(sigchld_received)) pause(); + + waitpid(pid, &status, 0); + ret = 0; + if(WIFEXITED(status)) + ret = WEXITSTATUS(status); + if(ret) goto start_error; - /* Now the trace is created, go on and create the supplementary files... */ - printf("Creating supplementary trace files\n"); ret = create_eventdefs(); if(ret) goto start_error; } else if(pid == 0) { /* child */ - int ret = - execlp(lttd_path, lttd_path, "-t", trace_root, "-c", channel_path, "-s", NULL); + + int ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", NULL); if(ret) { perror("Error in executing the lttd daemon"); exit(-1); @@ -406,6 +418,7 @@ int lttctl_daemon(struct lttctl_handle *handle, char *trace_name) /* error handling */ start_error: + printf("Trace start error\n"); ret |= lttctl_destroy_trace(handle, trace_name); create_error: return ret; diff --git a/ltt/branches/poly/lttd/lttd.c b/ltt/branches/poly/lttd/lttd.c index 3553dfae..02724ce5 100644 --- a/ltt/branches/poly/lttd/lttd.c +++ b/ltt/branches/poly/lttd/lttd.c @@ -67,7 +67,6 @@ static char *trace_name = NULL; static char *channel_name = NULL; static int daemon_mode = 0; static int append_mode = 0; -static int sig_parent = 0; volatile static int quit_program = 0; /* For signal handler */ /* Args : @@ -76,7 +75,7 @@ volatile static int quit_program = 0; /* For signal handler */ * -c directory Root directory of the relayfs trace channels. * -d Run in background (daemon). * -a Trace append mode. - * -s Send SIGIO to parent when ready for IO. + * -s Send SIGUSR1 to parent when ready for IO. */ void show_arguments(void) { @@ -87,7 +86,6 @@ void show_arguments(void) printf("-c directory Root directory of the relayfs trace channels.\n"); printf("-d Run in background (daemon).\n"); printf("-a Append to an possibly existing trace.\n"); - printf("-s Send SIGIO to parent when ready for IO.\n"); printf("\n"); } @@ -133,9 +131,6 @@ int parse_arguments(int argc, char **argv) case 'a': append_mode = 1; break; - case 's': - sig_parent = 1; - break; default: printf("Invalid argument '%s'.\n", argv[argn]); printf("\n"); @@ -410,9 +405,6 @@ int read_channels(struct channel_trace_fd *fd_pairs) pollfd[i].events = POLLIN|POLLPRI; } - /* Signal the parent that ready for IO */ - if(sig_parent) kill(getppid(), SIGIO); - while(1) { high_prio = 0; num_hup = 0; diff --git a/ltt/branches/poly/lttv/modules/gui/tracecontrol/tracecontrol.c b/ltt/branches/poly/lttv/modules/gui/tracecontrol/tracecontrol.c index 4097e0cd..75921a45 100644 --- a/ltt/branches/poly/lttv/modules/gui/tracecontrol/tracecontrol.c +++ b/ltt/branches/poly/lttv/modules/gui/tracecontrol/tracecontrol.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #define MAX_ARGS_LEN PATH_MAX * 10 @@ -304,7 +304,7 @@ gui_control(Tab *tab) tcd->fac_path_label = gtk_label_new("path to facilities:"); gtk_widget_show (tcd->fac_path_label); tcd->fac_path_entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/facilities"); + gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/" PACKAGE "/facilities"); gtk_widget_set_size_request(tcd->fac_path_entry, 250, -1); gtk_widget_show (tcd->fac_path_entry); gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->fac_path_label,0,2,12,13,GTK_FILL,GTK_FILL,2,2); @@ -449,32 +449,63 @@ void start_clicked (GtkButton *button, gpointer user_data) struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; - int nbdes; - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fdpty, &readfds); - - nbdes = select(fdpty+1, &readfds, NULL, NULL, &timeout); - - if(nbdes > 0) { - do { - count = read (fdpty, buf, 256); - if(count > 0) { - buf[count] = '\0'; - printf("%s", buf); - } - } while(select(fdpty+1, &readfds, NULL, NULL, &timeout) > 0); - - } else if(nbdes == -1) { - perror("Timeout occured when waiting for su password prompt"); - return; - } else { - g_warning("No data within 2 seconds when waiting for su prompt"); - return; - } + struct pollfd pollfd; + int num_rdy; + int num_hup = 0; + + + /* Read the output from the child terminal before the prompt. If no data in + * 200 ms, we stop reading to give the password */ + g_info("Reading from child console..."); + while(1) { + pollfd.fd = fdpty; + pollfd.events = POLLIN|POLLPRI; + + num_rdy = poll(&pollfd, 1, 200); +#if 0 + if(num_rdy == -1) { + perror("Poll error"); + goto wait_child; + } +#endif //0 + + /* Timeout : stop waiting for chars */ + if(num_rdy == 0) break; + + switch(pollfd.revents) { + case POLLERR: + g_warning("Error returned in polling fd\n"); + num_hup++; + break; + case POLLHUP: + g_info("Polling FD : hung up."); + num_hup++; + break; + case POLLNVAL: + g_warning("Polling fd tells it is not open"); + num_hup++; + break; + case POLLPRI: + case POLLIN: + count = read (fdpty, buf, 256); + if(count > 0) { + buf[count] = '\0'; + printf("%s", buf); + } else if(count == -1) { + perror("Error in read"); + goto wait_child; + } + break; + } + if(num_hup > 0) { + g_warning("Child hung up too fast"); + goto wait_child; + } + } + + /* Write the password */ g_info("Got su prompt, now writing password..."); - sleep(1); int ret; ret = write(fdpty, password, strlen(password)); if(ret < 0) perror("Error in write"); @@ -482,26 +513,60 @@ void start_clicked (GtkButton *button, gpointer user_data) if(ret < 0) perror("Error in write"); fsync(fdpty); - FD_ZERO(&readfds); - FD_SET(fdpty, &readfds); - do { - if (select(fdpty+1, &readfds, NULL, NULL, &timeout) < 0) { - g_warning("Cannot read from child pipe"); - return; + /* Take the output from the terminal and show it on the real console */ + g_info("Getting data from child terminal..."); + while(1) { + int num_hup = 0; + pollfd.fd = fdpty; + pollfd.events = POLLIN|POLLPRI; + + num_rdy = poll(&pollfd, 1, -1); +#if 0 + if(num_rdy == -1) { + perror("Poll error"); + goto wait_child; + } +#endif //0 + if(num_rdy == 0) break; + + switch(pollfd.revents) { + case POLLERR: + g_warning("Error returned in polling fd\n"); + num_hup++; + break; + case POLLHUP: + g_info("Polling FD : hung up."); + num_hup++; + break; + case POLLNVAL: + g_warning("Polling fd tells it is not open"); + num_hup++; + break; + case POLLPRI: + case POLLIN: + count = read (fdpty, buf, 256); + if(count > 0) { + buf[count] = '\0'; + printf("%s", buf); + } else if(count == -1) { + perror("Error in read"); + goto wait_child; + } + break; } - if(FD_ISSET(fdpty, &readfds)) { - count = read(fdpty, buf, 256); - buf[count] = '\0'; - printf("%s", buf); - } else FD_SET(fdpty, &readfds); - usleep(200); - } while(!(ret = waitpid(pid, &status, WNOHANG))); + if(num_hup > 0) goto wait_child; + } +wait_child: + g_info("Waiting for child exit..."); + + ret = waitpid(pid, &status, 0); - if(WIFEXITED(ret)) - if(WEXITSTATUS(ret) != 0) - g_warning("An error occured in the su command, exit code : %hhu", - WEXITSTATUS(ret)); + if(WIFEXITED(ret)) + if(WEXITSTATUS(ret) != 0) + g_warning("An error occured in the su command : %s", + strerror(WEXITSTATUS(ret))); + g_info("Child exited."); } else if(pid == 0) { /* child */ @@ -515,11 +580,26 @@ void start_clicked (GtkButton *button, gpointer user_data) setenv("LTT_FACILITIES", fac_path, 1); /* Setup arguments to su */ - strncpy(args, "\"", args_left); - args_left = MAX_ARGS_LEN - strlen(args) - 1; + //strncpy(args, "\'", args_left); + //args_left = MAX_ARGS_LEN - strlen(args) - 1; + /* Command */ + strncat(args, "exec", args_left); + args_left = MAX_ARGS_LEN - strlen(args) - 1; + + /* space */ + strncat(args, " ", args_left); + args_left = MAX_ARGS_LEN - strlen(args) - 1; + if(strcmp(lttctl_path, "") == 0) - lttctl_path = "lttctl"; + strncat(args, "lttctl", args_left); + else + strncat(args, lttctl_path, args_left); + args_left = MAX_ARGS_LEN - strlen(args) - 1; + + /* space */ + strncat(args, " ", args_left); + args_left = MAX_ARGS_LEN - strlen(args) - 1; /* channel dir */ strncat(args, "-l ", args_left); @@ -595,13 +675,13 @@ void start_clicked (GtkButton *button, gpointer user_data) strncat(args, subbuf_num, args_left); args_left = MAX_ARGS_LEN - strlen(args) - 1; } + + //strncat(args, "\'", args_left); + //args_left = MAX_ARGS_LEN - strlen(args) - 1; - strncat(args, "\"", args_left); - args_left = MAX_ARGS_LEN - strlen(args) - 1; - - //printf("Executing (as %s) : %s %s\n", username, lttctl_path, args); + g_message("Executing (as %s) : %s\n", username, args); - execlp("su", "su", "-p", "-c", lttctl_path, username, args, NULL); + execlp("su", "su", "-p", "-c", args, username, NULL); exit(-1); /* not supposed to happen! */ //system(args); //system("echo blah"); -- 2.34.1