]> sourceware.org Git - systemtap.git/blame - runtime/staprun/mainloop.c
rebased unwind_branch on top of current master
[systemtap.git] / runtime / staprun / mainloop.c
CommitLineData
a846e9cd
MH
1/* -*- linux-c -*-
2 *
3 * mainloop - staprun main loop
4 *
5 * This file is part of systemtap, and is free software. You can
6 * redistribute it and/or modify it under the terms of the GNU General
7 * Public License (GPL); either version 2, or (at your option) any
8 * later version.
9 *
9012e89f 10 * Copyright (C) 2005-2008 Red Hat Inc.
a846e9cd
MH
11 */
12
13#include "staprun.h"
5eddf13b 14#include <sys/utsname.h>
a846e9cd
MH
15
16/* globals */
a846e9cd 17int ncpus;
56bae342 18int use_old_transport = 0;
a846e9cd 19
83c5b5fe
MH
20static void sigproc(int signum)
21{
22 dbug(2, "sigproc %d (%s)\n", signum, strsignal(signum));
23
24 if (signum == SIGCHLD) {
25 pid_t pid = waitpid(-1, NULL, WNOHANG);
26 if (pid != target_pid)
27 return;
28 send_request(STP_EXIT, NULL, 0);
29 } else if (signum == SIGQUIT)
aaf2af3e 30 cleanup_and_exit(2);
83c5b5fe
MH
31 else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM)
32 send_request(STP_EXIT, NULL, 0);
33}
34
17dd0742 35static void setup_main_signals(int cleanup)
83c5b5fe
MH
36{
37 struct sigaction a;
38 memset(&a, 0, sizeof(a));
39 sigfillset(&a.sa_mask);
17dd0742
MH
40 if (cleanup == 0) {
41 a.sa_handler = sigproc;
42 sigaction(SIGCHLD, &a, NULL);
aaf2af3e 43 } else
17dd0742 44 a.sa_handler = SIG_IGN;
83c5b5fe
MH
45 sigaction(SIGINT, &a, NULL);
46 sigaction(SIGTERM, &a, NULL);
47 sigaction(SIGHUP, &a, NULL);
83c5b5fe
MH
48 sigaction(SIGQUIT, &a, NULL);
49}
50
a846e9cd
MH
51/*
52 * start_cmd forks the command given on the command line
53 * with the "-c" option. It will not exec that command
54 * until it received signal SIGUSR1. We do it this way because
55 * we must have the pid of the forked command so it can be set to
56 * the module and made available internally as _stp_target.
57 * SIGUSR1 is sent from stp_main_loop() below when it receives
58 * STP_START from the module.
59 */
60void start_cmd(void)
61{
62 pid_t pid;
63 sigset_t usrset;
b574c7b9
MH
64 struct sigaction a;
65
a846e9cd
MH
66 sigemptyset(&usrset);
67 sigaddset(&usrset, SIGUSR1);
83c5b5fe 68 pthread_sigmask(SIG_BLOCK, &usrset, NULL);
a846e9cd 69
b574c7b9
MH
70 /* if we are execing a target cmd, ignore ^C in stapio */
71 /* and let the target cmd get it. */
72 sigemptyset(&a.sa_mask);
73 a.sa_flags = 0;
74 a.sa_handler = SIG_IGN;
75 sigaction(SIGINT, &a, NULL);
76
aaf2af3e 77 dbug(1, "execing target_cmd %s\n", target_cmd);
a846e9cd 78 if ((pid = fork()) < 0) {
5eddf13b
DS
79 _perr("fork");
80 exit(1);
a846e9cd
MH
81 } else if (pid == 0) {
82 int signum;
83
b574c7b9
MH
84 a.sa_handler = SIG_DFL;
85 sigaction(SIGINT, &a, NULL);
86
8366a7a1 87 /* commands we fork need to run at normal priority */
aaf2af3e
FCE
88 setpriority(PRIO_PROCESS, 0, 0);
89
a846e9cd
MH
90 /* wait here until signaled */
91 sigwait(&usrset, &signum);
92
93 if (execl("/bin/sh", "sh", "-c", target_cmd, NULL) < 0)
94 perror(target_cmd);
5eddf13b 95 _exit(1);
a846e9cd
MH
96 }
97 target_pid = pid;
98}
99
100/**
101 * system_cmd() executes system commands in response
102 * to an STP_SYSTEM message from the module. These
103 * messages are sent by the system() systemtap function.
a846e9cd
MH
104 */
105void system_cmd(char *cmd)
106{
107 pid_t pid;
108
aaf2af3e 109 dbug(2, "system %s\n", cmd);
a846e9cd 110 if ((pid = fork()) < 0) {
5eddf13b 111 _perr("fork");
a846e9cd 112 } else if (pid == 0) {
aaf2af3e 113 setpriority(PRIO_PROCESS, 0, 0);
a846e9cd 114 if (execl("/bin/sh", "sh", "-c", cmd, NULL) < 0)
5eddf13b
DS
115 perr("%s", cmd);
116 _exit(1);
a846e9cd
MH
117 }
118}
119
5eddf13b
DS
120/* This is only used in the old relayfs code */
121static void read_buffer_info(void)
a846e9cd 122{
5eddf13b
DS
123 char buf[PATH_MAX];
124 struct statfs st;
125 int fd, len, ret;
126
127 if (!use_old_transport)
128 return;
129
aaf2af3e 130 if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC)
5eddf13b
DS
131 return;
132
133 if (sprintf_chk(buf, "/proc/systemtap/%s/bufsize", modname))
134 return;
135 fd = open(buf, O_RDONLY);
136 if (fd < 0)
137 return;
138
139 len = read(fd, buf, sizeof(buf));
140 if (len <= 0) {
141 perr("Couldn't read bufsize");
142 close(fd);
143 return;
144 }
145 ret = sscanf(buf, "%u,%u", &n_subbufs, &subbuf_size);
146 if (ret != 2)
147 perr("Couldn't read bufsize");
148
149 dbug(2, "n_subbufs= %u, size=%u\n", n_subbufs, subbuf_size);
150 close(fd);
151 return;
a846e9cd
MH
152}
153
a846e9cd 154/**
5eddf13b 155 * init_stapio - initialize the app
a846e9cd
MH
156 * @print_summary: boolean, print summary or not at end of run
157 *
158 * Returns 0 on success, negative otherwise.
159 */
5eddf13b 160int init_stapio(void)
a846e9cd 161{
5eddf13b 162 dbug(2, "init_stapio\n");
a846e9cd 163
5eddf13b 164 /* create control channel */
2972246a 165 use_old_transport = init_ctl_channel(0);
b38d9a7d 166 if (use_old_transport < 0) {
5eddf13b
DS
167 err("Failed to initialize control channel.\n");
168 return -1;
56bae342 169 }
5eddf13b 170 read_buffer_info();
56bae342 171
5d65678d 172 if (attach_mod) {
5eddf13b 173 dbug(2, "Attaching\n");
da5bc006
MH
174 if (use_old_transport) {
175 if (init_oldrelayfs() < 0) {
176 close_ctl_channel();
177 return -1;
aaf2af3e 178 }
da5bc006
MH
179 } else {
180 if (init_relayfs() < 0) {
181 close_ctl_channel();
182 return -1;
183 }
5d65678d
MH
184 }
185 return 0;
186 }
187
a846e9cd
MH
188 /* fork target_cmd if requested. */
189 /* It will not actually exec until signalled. */
190 if (target_cmd)
191 start_cmd();
192
193 return 0;
a846e9cd
MH
194}
195
5eddf13b
DS
196/* cleanup_and_exit() closed channels and frees memory
197 * then exits with the following status codes:
198 * 1 - failed to initialize.
199 * 2 - disconnected
200 * 3 - initialized
201 */
aaf2af3e 202void cleanup_and_exit(int closed)
a846e9cd 203{
a846e9cd
MH
204 pid_t err;
205 static int exiting = 0;
206
207 if (exiting)
208 return;
209 exiting = 1;
210
17dd0742
MH
211 setup_main_signals(1);
212
83c5b5fe 213 dbug(1, "CLEANUP AND EXIT closed=%d\n", closed);
a846e9cd
MH
214
215 /* what about child processes? we will wait for them here. */
216 err = waitpid(-1, NULL, WNOHANG);
217 if (err >= 0)
5eddf13b 218 err("\nWaiting for processes to exit\n");
aaf2af3e 219 while (wait(NULL) > 0) ;
a846e9cd 220
56bae342 221 if (use_old_transport)
da5bc006 222 close_oldrelayfs(closed == 2);
56bae342
MH
223 else
224 close_relayfs();
a846e9cd 225
83c5b5fe 226 dbug(1, "closing control channel\n");
a846e9cd
MH
227 close_ctl_channel();
228
5eddf13b 229 if (initialized == 2 && closed == 2) {
aaf2af3e 230 err("\nDisconnecting from systemtap module.\n" "To reconnect, type \"staprun -A %s\"\n", modname);
5eddf13b
DS
231 } else if (initialized)
232 closed = 3;
233 else
234 closed = 1;
235 exit(closed);
a846e9cd
MH
236}
237
a846e9cd
MH
238/**
239 * stp_main_loop - loop forever reading data
240 */
a846e9cd
MH
241
242int stp_main_loop(void)
243{
ff3e10e0 244 ssize_t nb;
a846e9cd 245 void *data;
aaf2af3e 246 uint32_t type;
a846e9cd 247 FILE *ofp = stdout;
264d469c 248 char recvbuf[8196];
a846e9cd
MH
249
250 setvbuf(ofp, (char *)NULL, _IOLBF, 0);
17dd0742 251 setup_main_signals(0);
a846e9cd 252
83c5b5fe 253 dbug(2, "in main loop\n");
9012e89f 254 send_request(STP_READY, NULL, 0);
a846e9cd 255
aaf2af3e 256 while (1) { /* handle messages from control channel */
a846e9cd
MH
257 nb = read(control_channel, recvbuf, sizeof(recvbuf));
258 if (nb <= 0) {
5eddf13b
DS
259 if (errno != EINTR)
260 _perr("Unexpected EOF in read (nb=%ld)", (long)nb);
a846e9cd
MH
261 continue;
262 }
a846e9cd 263
aaf2af3e
FCE
264 type = *(uint32_t *)recvbuf;
265 data = (void *)(recvbuf + sizeof(uint32_t));
266 nb -= sizeof(uint32_t);
267
268 switch (type) {
a846e9cd
MH
269#ifdef STP_OLD_TRANSPORT
270 case STP_REALTIME_DATA:
aaf2af3e
FCE
271 {
272 ssize_t bw = write(out_fd[0], data, nb);
273 if (bw >= 0 && bw != nb) {
274 nb = nb - bw;
275 bw = write(out_fd[0], data, nb);
276 }
277 if (bw != nb) {
278 _perr("write error (nb=%ld)", (long)nb);
279 cleanup_and_exit(1);
280 }
281 break;
ff3e10e0 282 }
a846e9cd
MH
283#endif
284 case STP_OOB_DATA:
aaf2af3e 285 fputs((char *)data, stderr);
a846e9cd 286 break;
aaf2af3e
FCE
287 case STP_EXIT:
288 {
289 /* module asks us to unload it and exit */
290 int *closed = (int *)data;
291 dbug(2, "got STP_EXIT, closed=%d\n", *closed);
292 cleanup_and_exit(*closed);
293 break;
294 }
295 case STP_START:
296 {
297 struct _stp_msg_start *t = (struct _stp_msg_start *)data;
298 dbug(2, "probe_start() returned %d\n", t->res);
299 if (t->res < 0) {
300 if (target_cmd)
301 kill(target_pid, SIGKILL);
302 cleanup_and_exit(1);
303 } else if (target_cmd)
304 kill(target_pid, SIGUSR1);
305 break;
306 }
a846e9cd 307 case STP_SYSTEM:
aaf2af3e
FCE
308 {
309 struct _stp_msg_cmd *c = (struct _stp_msg_cmd *)data;
310 dbug(2, "STP_SYSTEM: %s\n", c->cmd);
311 system_cmd(c->cmd);
312 break;
313 }
a846e9cd 314 case STP_TRANSPORT:
aaf2af3e
FCE
315 {
316 struct _stp_msg_start ts;
317 if (use_old_transport) {
318 if (init_oldrelayfs() < 0)
319 cleanup_and_exit(1);
320 } else {
321 if (init_relayfs() < 0)
322 cleanup_and_exit(1);
323 }
324 ts.target = target_pid;
325 initialized = 2;
326 send_request(STP_START, &ts, sizeof(ts));
327 if (load_only)
328 cleanup_and_exit(2);
329 break;
330 }
331 case STP_UNWIND:
332 {
333 int len;
334 char *ptr = (char *)data;
335 while (nb > 0) {
336 send_unwind_data(ptr);
337 len = strlen(ptr) + 1;
338 ptr += len;
339 nb -= len;
340 }
341 break;
a846e9cd 342 }
a846e9cd 343 default:
5eddf13b 344 err("WARNING: ignored message of type %d\n", (type));
a846e9cd
MH
345 }
346 }
347 fclose(ofp);
348 return 0;
349}
This page took 0.075422 seconds and 5 git commands to generate.