|
|
1be8bd |
commit b8d11c5e07aa1dcc8e7ec4ffff645d0589579dea
|
|
|
1be8bd |
Author: David Smith <dsmith@redhat.com>
|
|
|
1be8bd |
Date: Fri Jan 26 09:24:51 2018 -0600
|
|
|
1be8bd |
|
|
|
1be8bd |
BZ1527809 - Fix detaching from modules using SIGQUIT.
|
|
|
1be8bd |
|
|
|
1be8bd |
* staprun/mainloop.c: Put a "/* NOTREACHED */" comment after all calls to
|
|
|
1be8bd |
cleanup_and_exit() to remind the reader that cleanup_and_exit() doesn't
|
|
|
1be8bd |
return.
|
|
|
1be8bd |
(stp_main_loop): If we've got a pending interrupt,
|
|
|
1be8bd |
but 'load_only' is set, just detach instead of sending STP_EXIT to
|
|
|
1be8bd |
the module. Otherwise using SIGQUIT to detach fails and unloads the
|
|
|
1be8bd |
module.
|
|
|
1be8bd |
* staprun/monitor.c: Put a "/* NOTREACHED */" comment after all calls to
|
|
|
1be8bd |
cleanup_and_exit() to remind the reader that cleanup_and_exit() doesn't
|
|
|
1be8bd |
return.
|
|
|
1be8bd |
* testsuite/systemtap.base/attach_detach.exp: New test.
|
|
|
1be8bd |
|
|
|
1be8bd |
diff --git a/staprun/mainloop.c b/staprun/mainloop.c
|
|
|
1be8bd |
index a60372e..63b72cc 100644
|
|
|
1be8bd |
--- a/staprun/mainloop.c
|
|
|
1be8bd |
+++ b/staprun/mainloop.c
|
|
|
1be8bd |
@@ -648,6 +648,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (rc != 0) {
|
|
|
1be8bd |
perror ("Unable to send STP_READY");
|
|
|
1be8bd |
cleanup_and_exit(0, rc);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
|
|
|
1be8bd |
flags = fcntl(control_channel, F_GETFL);
|
|
|
1be8bd |
@@ -695,12 +696,28 @@ int stp_main_loop(void)
|
|
|
1be8bd |
|
|
|
1be8bd |
if (pending_interrupts) {
|
|
|
1be8bd |
int btype = STP_EXIT;
|
|
|
1be8bd |
- int rc = write(control_channel, &btype, sizeof(btype));
|
|
|
1be8bd |
+ int rc;
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+ /* If 'load_only' is set, we don't want to send STP_EXIT,
|
|
|
1be8bd |
+ * which would cause any 'probe end' processing to be
|
|
|
1be8bd |
+ * done. Instead, we'll just detach by calling
|
|
|
1be8bd |
+ * cleanup_and_exit(). This should let the module continue to
|
|
|
1be8bd |
+ * run. */
|
|
|
1be8bd |
+ if (load_only)
|
|
|
1be8bd |
+ {
|
|
|
1be8bd |
+ cleanup_and_exit(load_only /* = detach */, 0);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+ rc = write(control_channel, &btype, sizeof(btype));
|
|
|
1be8bd |
dbug(2, "signal-triggered %d exit rc %d\n", pending_interrupts, rc);
|
|
|
1be8bd |
- if (monitor || (pending_interrupts > 2)) /* user mashing on ^C multiple times */
|
|
|
1be8bd |
- cleanup_and_exit (load_only /* = detach */, 0);
|
|
|
1be8bd |
+ if (monitor || (pending_interrupts > 2))
|
|
|
1be8bd |
+ { /* user mashing on ^C multiple times */
|
|
|
1be8bd |
+ cleanup_and_exit (load_only /* = detach */, 0);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
else
|
|
|
1be8bd |
- {} /* await STP_EXIT reply message to kill staprun */
|
|
|
1be8bd |
+ {} /* await STP_EXIT reply message to kill staprun */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
|
|
|
1be8bd |
/* If the runtime does not implement select() on the command
|
|
|
1be8bd |
@@ -719,6 +736,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (nb >= 0 || (errno != EINTR && errno != EAGAIN)) {
|
|
|
1be8bd |
_perr(_("Unexpected EOF in read (nb=%ld)"), (long)nb);
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
|
|
|
1be8bd |
if (!select_supported) {
|
|
|
1be8bd |
@@ -736,6 +754,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
{
|
|
|
1be8bd |
_perr(_("Unexpected error in select"));
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
}
|
|
|
1be8bd |
continue;
|
|
|
1be8bd |
@@ -750,6 +769,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (write_realtime_data(recvbuf.payload.data, nb)) {
|
|
|
1be8bd |
_perr(_("write error (nb=%ld)"), (long)nb);
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
break;
|
|
|
1be8bd |
#endif
|
|
|
1be8bd |
@@ -841,8 +861,10 @@ int stp_main_loop(void)
|
|
|
1be8bd |
dbug(2, "got STP_EXIT\n");
|
|
|
1be8bd |
if (monitor)
|
|
|
1be8bd |
monitor_exited();
|
|
|
1be8bd |
- else
|
|
|
1be8bd |
+ else {
|
|
|
1be8bd |
cleanup_and_exit(0, error_detected);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
/* monitor mode exit handled elsewhere, later. */
|
|
|
1be8bd |
break;
|
|
|
1be8bd |
}
|
|
|
1be8bd |
@@ -863,6 +885,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (target_cmd)
|
|
|
1be8bd |
kill(target_pid, SIGKILL);
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
} else if (target_cmd) {
|
|
|
1be8bd |
dbug(1, "detaching pid %d\n", target_pid);
|
|
|
1be8bd |
#if WORKAROUND_BZ467568
|
|
|
1be8bd |
@@ -878,6 +901,7 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (target_cmd)
|
|
|
1be8bd |
kill(target_pid, SIGKILL);
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
#endif
|
|
|
1be8bd |
}
|
|
|
1be8bd |
@@ -901,20 +925,24 @@ int stp_main_loop(void)
|
|
|
1be8bd |
struct _stp_msg_start ts;
|
|
|
1be8bd |
struct _stp_msg_ns_pid nspid;
|
|
|
1be8bd |
if (use_old_transport) {
|
|
|
1be8bd |
- if (init_oldrelayfs() < 0)
|
|
|
1be8bd |
+ if (init_oldrelayfs() < 0) {
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
} else {
|
|
|
1be8bd |
if (init_relayfs() < 0)
|
|
|
1be8bd |
cleanup_and_exit(0, 1);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
|
|
|
1be8bd |
if (target_namespaces_pid > 0) {
|
|
|
1be8bd |
nspid.target = target_namespaces_pid;
|
|
|
1be8bd |
rc = send_request(STP_NAMESPACES_PID, &nspid, sizeof(nspid));
|
|
|
1be8bd |
if (rc != 0) {
|
|
|
1be8bd |
- perror ("Unable to send STP_NAMESPACES_PID");
|
|
|
1be8bd |
- cleanup_and_exit (1, rc);
|
|
|
1be8bd |
- }
|
|
|
1be8bd |
+ perror ("Unable to send STP_NAMESPACES_PID");
|
|
|
1be8bd |
+ cleanup_and_exit (1, rc);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
}
|
|
|
1be8bd |
|
|
|
1be8bd |
ts.target = target_pid;
|
|
|
1be8bd |
@@ -922,9 +950,12 @@ int stp_main_loop(void)
|
|
|
1be8bd |
if (rc != 0) {
|
|
|
1be8bd |
perror ("Unable to send STP_START");
|
|
|
1be8bd |
cleanup_and_exit(0, rc);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
}
|
|
|
1be8bd |
- if (load_only)
|
|
|
1be8bd |
+ if (load_only) {
|
|
|
1be8bd |
cleanup_and_exit(1, 0);
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
break;
|
|
|
1be8bd |
}
|
|
|
1be8bd |
default:
|
|
|
1be8bd |
diff --git a/staprun/monitor.c b/staprun/monitor.c
|
|
|
1be8bd |
index 6b8bb11..478634c 100644
|
|
|
1be8bd |
--- a/staprun/monitor.c
|
|
|
1be8bd |
+++ b/staprun/monitor.c
|
|
|
1be8bd |
@@ -598,7 +598,10 @@ void monitor_input(void)
|
|
|
1be8bd |
break;
|
|
|
1be8bd |
case 'q':
|
|
|
1be8bd |
if (monitor_state == exited)
|
|
|
1be8bd |
- cleanup_and_exit(0, 0 /* error_detected unavailable here */ );
|
|
|
1be8bd |
+ {
|
|
|
1be8bd |
+ cleanup_and_exit(0, 0 /* error_detected unavailable here */ );
|
|
|
1be8bd |
+ /* NOTREACHED */
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
else
|
|
|
1be8bd |
write_command("quit");
|
|
|
1be8bd |
break;
|
|
|
1be8bd |
diff --git a/testsuite/systemtap.base/attach_detach.exp b/testsuite/systemtap.base/attach_detach.exp
|
|
|
1be8bd |
new file mode 100644
|
|
|
1be8bd |
index 0000000..ef23615
|
|
|
1be8bd |
--- /dev/null
|
|
|
1be8bd |
+++ b/testsuite/systemtap.base/attach_detach.exp
|
|
|
1be8bd |
@@ -0,0 +1,145 @@
|
|
|
1be8bd |
+set test "attach_detach"
|
|
|
1be8bd |
+if {![installtest_p]} { untested $test; return }
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+set test_script { "
|
|
|
1be8bd |
+ probe begin { printf(\"begin probe fired\\n\") }
|
|
|
1be8bd |
+ probe timer.s(5) { printf(\"timer probe fired\\n\") }
|
|
|
1be8bd |
+ probe end { printf(\"end probe fired\\n\") }
|
|
|
1be8bd |
+" }
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# First, compile a module.
|
|
|
1be8bd |
+stap_compile $test 1 $test_script -m attach_detach
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# stap_compile does pass/fail, but doesn't return a status. So, if
|
|
|
1be8bd |
+# attach_detach.ko exists, it worked.
|
|
|
1be8bd |
+if {! [file exists attach_detach.ko]} {
|
|
|
1be8bd |
+ return
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Load the module and detach.
|
|
|
1be8bd |
+set subtest "initial load"
|
|
|
1be8bd |
+spawn staprun -L attach_detach.ko
|
|
|
1be8bd |
+set fail 0
|
|
|
1be8bd |
+set pass 0
|
|
|
1be8bd |
+expect {
|
|
|
1be8bd |
+ -timeout 120
|
|
|
1be8bd |
+ -re "^begin probe fired\r\n" { incr fail; exp_continue }
|
|
|
1be8bd |
+ -re "^\r\n" { exp_continue }
|
|
|
1be8bd |
+ -re "^Disconnecting from systemtap module.\r\n" {
|
|
|
1be8bd |
+ incr pass; exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
|
|
|
1be8bd |
+ incr pass
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ eof { fail "$test ($subtest) - EOF"; incr fail }
|
|
|
1be8bd |
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+catch {close}; catch {wait}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+if {$fail == 0 && $pass == 2} {
|
|
|
1be8bd |
+ pass "$test ($subtest) - disconnect seen"
|
|
|
1be8bd |
+} else {
|
|
|
1be8bd |
+ fail "$test ($subtest) - begin seen ($fail $pass)"
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Make sure the module is still loaded.
|
|
|
1be8bd |
+if {[catch { exec lsmod | grep attach_detach >/dev/null }]} {
|
|
|
1be8bd |
+ fail "$test ($subtest) - module still present"
|
|
|
1be8bd |
+ return
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+pass "$test ($subtest) - module still present"
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Attach to the module, then use SIGQUIT to detach again.
|
|
|
1be8bd |
+set subtest "attach and SIGQUIT"
|
|
|
1be8bd |
+spawn staprun -A attach_detach
|
|
|
1be8bd |
+set fail 0
|
|
|
1be8bd |
+set pass 0
|
|
|
1be8bd |
+set timer_probe_seen 0
|
|
|
1be8bd |
+expect {
|
|
|
1be8bd |
+ -timeout 120
|
|
|
1be8bd |
+ -re "^begin probe fired\r\n" { incr pass; exp_continue }
|
|
|
1be8bd |
+ -re "^end probe fired\r\n" { incr fail; exp_continue }
|
|
|
1be8bd |
+ -re "^timer probe fired\r\n" {
|
|
|
1be8bd |
+ if {!$timer_probe_seen} {
|
|
|
1be8bd |
+ set timer_probe_seen 1
|
|
|
1be8bd |
+ incr pass
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+ # Send our staprun process a SIGQUIT, to make it detach.
|
|
|
1be8bd |
+ kill SIGQUIT [exp_pid]
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ -re "^\r\n" { exp_continue }
|
|
|
1be8bd |
+ -re "^Disconnecting from systemtap module.\r\n" {
|
|
|
1be8bd |
+ incr pass; exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
|
|
|
1be8bd |
+ incr pass
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ eof { fail "$test ($subtest) - EOF"; incr fail }
|
|
|
1be8bd |
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+catch {close}; catch {wait}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+if {$fail == 0 && $pass == 4} {
|
|
|
1be8bd |
+ pass "$test ($subtest) - disconnect seen"
|
|
|
1be8bd |
+} else {
|
|
|
1be8bd |
+ fail "$test ($subtest) - no disconnect seen ($fail $pass)"
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Make sure the module is still loaded.
|
|
|
1be8bd |
+if {[catch { exec lsmod | grep attach_detach >/dev/null}]} {
|
|
|
1be8bd |
+ fail "$test ($subtest) - module still present"
|
|
|
1be8bd |
+ return
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+pass "$test ($subtest) - module still present"
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Attach one last time, then use SIGTERM to unload the module and quit.
|
|
|
1be8bd |
+set subtest "attach and SIGTERM"
|
|
|
1be8bd |
+spawn staprun -A attach_detach
|
|
|
1be8bd |
+set fail 0
|
|
|
1be8bd |
+set pass 0
|
|
|
1be8bd |
+set timer_probe_seen 0
|
|
|
1be8bd |
+expect {
|
|
|
1be8bd |
+ -timeout 120
|
|
|
1be8bd |
+ -re "^begin probe fired\r\n" { incr fail; exp_continue }
|
|
|
1be8bd |
+ -re "^end probe fired\r\n" { incr pass }
|
|
|
1be8bd |
+ -re "^timer probe fired\r\n" {
|
|
|
1be8bd |
+ if {!$timer_probe_seen} {
|
|
|
1be8bd |
+ set timer_probe_seen 1
|
|
|
1be8bd |
+ incr pass
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+ # Send our staprun process a SIGTERM, to make it quit and
|
|
|
1be8bd |
+ # unload.
|
|
|
1be8bd |
+ kill SIGTERM [exp_pid]
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ -re "^\r\n" { exp_continue }
|
|
|
1be8bd |
+ -re "^Disconnecting from systemtap module.\r\n" {
|
|
|
1be8bd |
+ incr fail; exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
|
|
|
1be8bd |
+ incr fail; exp_continue
|
|
|
1be8bd |
+ }
|
|
|
1be8bd |
+ eof { fail "$test ($subtest) - EOF"; incr fail }
|
|
|
1be8bd |
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+catch {close}; catch {wait}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+if {$fail == 0 && $pass == 2} {
|
|
|
1be8bd |
+ pass "$test ($subtest) - quit seen"
|
|
|
1be8bd |
+} else {
|
|
|
1be8bd |
+ fail "$test ($subtest) - no quit seen ($fail $pass)"
|
|
|
1be8bd |
+}
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+# Make sure the module isn't still loaded.
|
|
|
1be8bd |
+if {[catch { exec lsmod | grep attach_detach >/dev/null}]} {
|
|
|
1be8bd |
+ pass "$test ($subtest) - module is gone"
|
|
|
1be8bd |
+} else {
|
|
|
1be8bd |
+ fail "$test ($subtest) - module is gone"
|
|
|
1be8bd |
+
|
|
|
1be8bd |
+ # If for some odd reason the module is still loaded, try to unload
|
|
|
1be8bd |
+ # it.
|
|
|
1be8bd |
+ catch { exec staprun -d attach_detach }
|
|
|
1be8bd |
+}
|