summaryrefslogtreecommitdiffstats
path: root/runtime/staprun/mainloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/staprun/mainloop.c')
-rw-r--r--runtime/staprun/mainloop.c302
1 files changed, 107 insertions, 195 deletions
diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c
index 7b8c5e31..4acfb001 100644
--- a/runtime/staprun/mainloop.c
+++ b/runtime/staprun/mainloop.c
@@ -11,23 +11,12 @@
*/
#include "staprun.h"
+#include <sys/utsname.h>
/* globals */
-int control_channel = 0;
int ncpus;
int use_old_transport = 0;
-#define ERR_MSG "\nUNEXPECTED FATAL ERROR in staprun. Please file a bug report.\n"
-void fatal_handler (int signum)
-{
- int rc;
- char *str = strsignal(signum);
- rc = write (STDERR_FILENO, ERR_MSG, sizeof(ERR_MSG));
- rc = write (STDERR_FILENO, str, strlen(str));
- rc = write (STDERR_FILENO, "\n", 1);
- _exit(-1);
-}
-
static void sigproc(int signum)
{
dbug(2, "sigproc %d (%s)\n", signum, strsignal(signum));
@@ -60,56 +49,6 @@ static void setup_main_signals(int cleanup)
sigaction(SIGQUIT, &a, NULL);
}
-void setup_signals(void)
-{
- sigset_t s;
- struct sigaction a;
-
- /* blocking all signals while we set things up */
- sigfillset(&s);
- pthread_sigmask(SIG_SETMASK, &s, NULL);
-
- /* set some of them to be ignored */
- memset(&a, 0, sizeof(a));
- sigfillset(&a.sa_mask);
- a.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &a, NULL);
- sigaction(SIGUSR2, &a, NULL);
-
- /* for serious errors, handle them in fatal_handler */
- a.sa_handler = fatal_handler;
- sigaction(SIGBUS, &a, NULL);
- sigaction(SIGFPE, &a, NULL);
- sigaction(SIGILL, &a, NULL);
- sigaction(SIGSEGV, &a, NULL);
- sigaction(SIGXCPU, &a, NULL);
- sigaction(SIGXFSZ, &a, NULL);
-
- /* unblock all signals */
- sigemptyset(&s);
- pthread_sigmask(SIG_SETMASK, &s, NULL);
-}
-
-
-/**
- * send_request - send request to kernel over control channel
- * @type: the relay-app command id
- * @data: pointer to the data to be sent
- * @len: length of the data to be sent
- *
- * Returns 0 on success, negative otherwise.
- */
-int send_request(int type, void *data, int len)
-{
- char buf[1024];
- if (len > (int)sizeof(buf)) {
- err("exceeded maximum send_request size.\n");
- return -1;
- }
- memcpy(buf, &type, 4);
- memcpy(&buf[4],data,len);
- return write(control_channel, buf, len+4);
-}
/*
* start_cmd forks the command given on the command line
@@ -131,23 +70,17 @@ void start_cmd(void)
dbug (1, "execing target_cmd %s\n", target_cmd);
if ((pid = fork()) < 0) {
- perror ("fork");
- exit(-1);
+ _perr("fork");
+ exit(1);
} else if (pid == 0) {
int signum;
- if (setregid(cmd_gid, cmd_gid) < 0) {
- perror("setregid");
- }
- if (setreuid(cmd_uid, cmd_uid) < 0) {
- perror("setreuid");
- }
/* wait here until signaled */
sigwait(&usrset, &signum);
if (execl("/bin/sh", "sh", "-c", target_cmd, NULL) < 0)
perror(target_cmd);
- _exit(-1);
+ _exit(1);
}
target_pid = pid;
}
@@ -156,8 +89,6 @@ void start_cmd(void)
* system_cmd() executes system commands in response
* to an STP_SYSTEM message from the module. These
* messages are sent by the system() systemtap function.
- * uid and gid are set because staprun is running as root and
- * it is best to run commands as the real user.
*/
void system_cmd(char *cmd)
{
@@ -165,57 +96,104 @@ void system_cmd(char *cmd)
dbug (2, "system %s\n", cmd);
if ((pid = fork()) < 0) {
- perror ("fork");
+ _perr("fork");
} else if (pid == 0) {
- if (setregid(cmd_gid, cmd_gid) < 0) {
- perror("setregid");
- }
- if (setreuid(cmd_uid, cmd_uid) < 0) {
- perror("setreuid");
- }
if (execl("/bin/sh", "sh", "-c", cmd, NULL) < 0)
- perror(cmd);
- _exit(-1);
+ perr("%s", cmd);
+ _exit(1);
}
}
+static int using_old_transport(void)
+{
+ struct utsname utsbuf;
+ int i;
+ long int kver[3];
+ char *start, *end;
-/* stp_check script */
-#ifdef PKGLIBDIR
-char *stp_check=PKGLIBDIR "/stp_check";
-#else
-char *stp_check="stp_check";
-#endif
+ if (uname(&utsbuf) != 0) {
+ _perr("Unable to determine kernel version, uname failed");
+ return -1;
+ }
+
+ start = utsbuf.release;
+ for (i = 0; i < 3; i++) {
+ errno = 0;
+ kver[i] = strtol(start, &end, 10);
+ if (errno != 0) {
+ _perr("Unable to parse kernel version, strtol failed");
+ return -1;
+ }
+ start = end;
+ start++;
+ }
-static int run_stp_check (void)
+ if (KERNEL_VERSION(kver[0], kver[1], kver[2])
+ <= KERNEL_VERSION(2, 6, 15)) {
+ dbug(2, "Using OLD TRANSPORT\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* This is only used in the old relayfs code */
+static void read_buffer_info(void)
{
- int ret ;
- /* run the _stp_check script */
- dbug(2, "executing %s\n", stp_check);
- ret = system(stp_check);
- return ret;
+ char buf[PATH_MAX];
+ struct statfs st;
+ int fd, len, ret;
+
+ if (!use_old_transport)
+ return;
+
+ if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC)
+ return;
+
+ if (sprintf_chk(buf, "/proc/systemtap/%s/bufsize", modname))
+ return;
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ len = read(fd, buf, sizeof(buf));
+ if (len <= 0) {
+ perr("Couldn't read bufsize");
+ close(fd);
+ return;
+ }
+ ret = sscanf(buf, "%u,%u", &n_subbufs, &subbuf_size);
+ if (ret != 2)
+ perr("Couldn't read bufsize");
+
+ dbug(2, "n_subbufs= %u, size=%u\n", n_subbufs, subbuf_size);
+ close(fd);
+ return;
}
+
/**
- * init_stp - initialize the app
+ * init_stapio - initialize the app
* @print_summary: boolean, print summary or not at end of run
*
* Returns 0 on success, negative otherwise.
*/
-int init_staprun(void)
+int init_stapio(void)
{
- char bufcmd[128];
- int rstatus;
- int pid;
+ dbug(2, "init_stapio\n");
- if (system(VERSION_CMD)) {
- dbug(2, "Using OLD TRANSPORT\n");
- use_old_transport = 1;
+ use_old_transport = using_old_transport();
+ if (use_old_transport < 0)
+ return -1;
+
+ /* create control channel */
+ if (init_ctl_channel() < 0) {
+ err("Failed to initialize control channel.\n");
+ return -1;
}
+ read_buffer_info();
if (attach_mod) {
- if (init_ctl_channel() < 0)
- return -1;
+ dbug(2, "Attaching\n");
if (use_old_transport) {
if (init_oldrelayfs() < 0) {
close_ctl_channel();
@@ -230,57 +208,22 @@ int init_staprun(void)
return 0;
}
- if (run_stp_check() < 0)
- return -1;
-
- /* insert module */
- sprintf(bufcmd, "_stp_bufsize=%d", buffer_size);
- modoptions[0] = "insmod";
- modoptions[1] = modpath;
- modoptions[2] = bufcmd;
- /* modoptions[3...N] set by command line parser. */
-
- if ((pid = fork()) < 0) {
- perror ("fork");
- exit(-1);
- } else if (pid == 0) {
- if (execvp("/sbin/insmod", modoptions) < 0)
- _exit(-1);
- }
- if (waitpid(pid, &rstatus, 0) < 0) {
- perror("waitpid");
- exit(-1);
- }
- if (WIFEXITED(rstatus) && WEXITSTATUS(rstatus)) {
- fprintf(stderr, "ERROR, couldn't insmod probe module %s\n", modpath);
- return -1;
- }
-
- /* create control channel */
- if (init_ctl_channel() < 0) {
- err("Failed to initialize control channel.\n");
- goto exit1;
- }
-
/* fork target_cmd if requested. */
/* It will not actually exec until signalled. */
if (target_cmd)
start_cmd();
return 0;
-
-exit1:
- snprintf(bufcmd, sizeof(bufcmd), "/sbin/rmmod -w %s", modname);
- if (system(bufcmd))
- fprintf(stderr, "ERROR: couldn't rmmod probe module %s.\n", modname);
- return -1;
}
-
-
+/* cleanup_and_exit() closed channels and frees memory
+ * then exits with the following status codes:
+ * 1 - failed to initialize.
+ * 2 - disconnected
+ * 3 - initialized
+ */
void cleanup_and_exit (int closed)
{
- char tmpbuf[128];
pid_t err;
static int exiting = 0;
@@ -295,7 +238,7 @@ void cleanup_and_exit (int closed)
/* what about child processes? we will wait for them here. */
err = waitpid(-1, NULL, WNOHANG);
if (err >= 0)
- fprintf(stderr,"\nWaiting for processes to exit\n");
+ err("\nWaiting for processes to exit\n");
while(wait(NULL) > 0) ;
if (use_old_transport)
@@ -306,22 +249,16 @@ void cleanup_and_exit (int closed)
dbug(1, "closing control channel\n");
close_ctl_channel();
- if (closed == 0) {
- dbug(1, "removing module\n");
- snprintf(tmpbuf, sizeof(tmpbuf), "/sbin/rmmod -w %s", modname);
- if (system(tmpbuf)) {
- fprintf(stderr, "ERROR: couldn't rmmod probe module %s.\n", modname);
- exit(1);
- }
- } else if (closed == 2) {
- fprintf(stderr, "\nDisconnecting from systemtap module.\n");
- fprintf(stderr, "To reconnect, type \"staprun -A %s\"\n", modname);
- }
-
- exit(0);
+ if (initialized == 2 && closed == 2) {
+ err("\nDisconnecting from systemtap module.\n" \
+ "To reconnect, type \"staprun -A %s\"\n", modname);
+ } else if (initialized)
+ closed = 3;
+ else
+ closed = 1;
+ exit(closed);
}
-
/**
* stp_main_loop - loop forever reading data
*/
@@ -342,13 +279,11 @@ int stp_main_loop(void)
while (1) { /* handle messages from control channel */
nb = read(control_channel, recvbuf, sizeof(recvbuf));
if (nb <= 0) {
- if (errno != EINTR) {
- perror("recv");
- fprintf(stderr, "WARNING: unexpected EOF. nb=%ld\n", (long)nb);
- }
+ if (errno != EINTR)
+ _perr("Unexpected EOF in read (nb=%ld)", (long)nb);
continue;
}
-
+
type = *(int *)recvbuf;
data = (void *)(recvbuf + sizeof(int));
@@ -362,10 +297,8 @@ int stp_main_loop(void)
bw = write(out_fd[0], data, nb - sizeof(int));
}
if (bw != (nb - (ssize_t)sizeof(int))) {
- perror("write");
- fprintf(stderr,
- "ERROR: write error. nb=%ld\n", (long)nb);
- cleanup_and_exit(0);
+ _perr("write error (nb=%ld)", (long)nb);
+ cleanup_and_exit(1);
}
break;
}
@@ -388,7 +321,7 @@ int stp_main_loop(void)
if (t->res < 0) {
if (target_cmd)
kill (target_pid, SIGKILL);
- cleanup_and_exit(0);
+ cleanup_and_exit(1);
} else if (target_cmd)
kill (target_pid, SIGUSR1);
break;
@@ -405,41 +338,20 @@ int stp_main_loop(void)
struct _stp_msg_start ts;
if (use_old_transport) {
if (init_oldrelayfs() < 0)
- cleanup_and_exit(0);
+ cleanup_and_exit(1);
} else {
if (init_relayfs() < 0)
- cleanup_and_exit(0);
+ cleanup_and_exit(1);
}
ts.target = target_pid;
+ initialized = 2;
send_request(STP_START, &ts, sizeof(ts));
if (load_only)
cleanup_and_exit(2);
break;
}
- case STP_MODULE:
- {
- dbug(2, "STP_MODULES request received\n");
- do_module(data);
- break;
- }
- case STP_SYMBOLS:
- {
- struct _stp_msg_symbol *req = (struct _stp_msg_symbol *)data;
- dbug(2, "STP_SYMBOLS request received\n");
- if (req->endian != 0x1234) {
- fprintf(stderr,"ERROR: staprun is compiled with different endianess than the kernel!\n");
- cleanup_and_exit(0);
- }
- if (req->ptr_size != sizeof(char *)) {
- fprintf(stderr,"ERROR: staprun is compiled with %d-bit pointers and the kernel uses %d-bit.\n",
- 8*(int)sizeof(char *), 8*req->ptr_size);
- cleanup_and_exit(0);
- }
- do_kernel_symbols();
- break;
- }
default:
- fprintf(stderr, "WARNING: ignored message of type %d\n", (type));
+ err("WARNING: ignored message of type %d\n", (type));
}
}
fclose(ofp);