diff options
author | Petr Machata <pmachata@redhat.com> | 2012-04-11 18:01:44 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-04-11 18:01:44 +0200 |
commit | ffe4cd25089680daf1bd1ec0114d177ec3e0cf95 (patch) | |
tree | 68cbebfb7e1de8633af2a305985ccb784d20c770 | |
parent | cec06ec8282c538a40bde968ae36fe8356daffaa (diff) | |
download | ltrace-ffe4cd25089680daf1bd1ec0114d177ec3e0cf95.tar.gz |
Handle detach from sleeping or unresponsive processes
-rw-r--r-- | common.h | 17 | ||||
-rw-r--r-- | handle_event.c | 7 | ||||
-rw-r--r-- | libltrace.c | 9 | ||||
-rw-r--r-- | sysdeps/linux-gnu/events.c | 6 | ||||
-rw-r--r-- | sysdeps/linux-gnu/trace.c | 15 |
5 files changed, 46 insertions, 8 deletions
@@ -347,7 +347,6 @@ extern void continue_after_signal(pid_t pid, int signum); extern void continue_after_syscall(Process *proc, int sysnum, int ret_p); extern void continue_after_breakpoint(Process * proc, Breakpoint * sbp); extern void continue_after_vfork(Process * proc); -extern void ltrace_exiting(void); extern long gimme_arg(enum tof type, Process * proc, int arg_num, arg_type_info * info); extern void save_register_args(enum tof type, Process * proc); extern int umovestr(Process * proc, void * addr, int len, void * laddr); @@ -363,6 +362,22 @@ extern int task_kill (pid_t pid, int sig); * any platform-specific knowledge of why it could be so. */ void trace_fail_warning(pid_t pid); +/* A pair of functions called to initiate a detachment request when + * ltrace is about to exit. Their job is to undo any effects that + * tracing had and eventually detach process, perhaps by way of + * installing a process handler. + * + * OS_LTRACE_EXITING_SIGHANDLER is called from a signal handler + * context right after the signal was captured. It returns 1 if the + * request was handled or 0 if it wasn't. + * + * If the call to OS_LTRACE_EXITING_SIGHANDLER didn't handle the + * request, OS_LTRACE_EXITING is called when the next event is + * generated. Therefore it's called in "safe" context, without + * re-entrancy concerns, but it's only called after an even is + * generated. */ +int os_ltrace_exiting_sighandler(void); +void os_ltrace_exiting(void); extern struct ltelf main_lte; diff --git a/handle_event.c b/handle_event.c index e3d3d0a..725f50d 100644 --- a/handle_event.c +++ b/handle_event.c @@ -49,11 +49,12 @@ call_handler(Process * proc, Event * event) } void -handle_event(Event *event) { +handle_event(Event *event) +{ if (exiting == 1) { - exiting = 2; debug(1, "ltrace about to exit"); - ltrace_exiting(); + os_ltrace_exiting(); + exiting = 2; } debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", event->proc ? event->proc->pid : -1, event->type); diff --git a/libltrace.c b/libltrace.c index 19bfafd..777ad1b 100644 --- a/libltrace.c +++ b/libltrace.c @@ -48,9 +48,14 @@ signal_alarm(int sig) { } static void -signal_exit(int sig) { - exiting = 1; +signal_exit(int sig) +{ debug(1, "Received interrupt signal; exiting..."); + if (exiting != 0) + return; + + exiting = 1 + !!os_ltrace_exiting_sighandler(); + signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGALRM, signal_alarm); diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c index 021192f..b6c12ef 100644 --- a/sysdeps/linux-gnu/events.c +++ b/sysdeps/linux-gnu/events.c @@ -104,6 +104,8 @@ next_qd_event(void) return each_qd_event(&event_process_not_reenabling, NULL); } +int linux_in_waitpid = 0; + Event * next_event(void) { @@ -124,7 +126,11 @@ next_event(void) debug(DEBUG_EVENT, "event: No more traced programs: exiting"); exit(0); } + + linux_in_waitpid = 1; pid = waitpid(-1, &status, __WALL); + linux_in_waitpid = 0; + if (pid == -1) { if (errno == ECHILD) { debug(DEBUG_EVENT, "event: No more traced programs: exiting"); diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c index 82a4154..9ecea1e 100644 --- a/sysdeps/linux-gnu/trace.c +++ b/sysdeps/linux-gnu/trace.c @@ -314,8 +314,8 @@ task_stopped(Process * task, void * data) case ps_invalid: case ps_tracing_stop: case ps_zombie: - case ps_sleeping: return pcb_cont; + case ps_sleeping: case ps_stop: case ps_other: return pcb_stop; @@ -1005,7 +1005,7 @@ continue_after_syscall(Process * proc, int sysnum, int ret_p) * detaches. */ void -ltrace_exiting(void) +os_ltrace_exiting(void) { struct opt_p_t * it; for (it = opt_p; it != NULL; it = it->next) { @@ -1019,6 +1019,17 @@ ltrace_exiting(void) } } +int +os_ltrace_exiting_sighandler(void) +{ + extern int linux_in_waitpid; + if (linux_in_waitpid) { + os_ltrace_exiting(); + return 1; + } + return 0; +} + size_t umovebytes(Process *proc, void *addr, void *laddr, size_t len) { |