if (rc != 0) {
perror ("Unable to send STP_READY");
cleanup_and_exit(0, rc);
+ /* NOTREACHED */
}
flags = fcntl(control_channel, F_GETFL);
if (pending_interrupts) {
int btype = STP_EXIT;
- int rc = write(control_channel, &btype, sizeof(btype));
+ int rc;
+
+ /* If 'load_only' is set, we don't want to send STP_EXIT,
+ * which would cause any 'probe end' processing to be
+ * done. Instead, we'll just detach by calling
+ * cleanup_and_exit(). This should let the module continue to
+ * run. */
+ if (load_only)
+ {
+ cleanup_and_exit(load_only /* = detach */, 0);
+ /* NOTREACHED */
+ }
+
+ rc = write(control_channel, &btype, sizeof(btype));
dbug(2, "signal-triggered %d exit rc %d\n", pending_interrupts, rc);
- if (monitor || (pending_interrupts > 2)) /* user mashing on ^C multiple times */
- cleanup_and_exit (load_only /* = detach */, 0);
+ if (monitor || (pending_interrupts > 2))
+ { /* user mashing on ^C multiple times */
+ cleanup_and_exit (load_only /* = detach */, 0);
+ /* NOTREACHED */
+ }
else
- {} /* await STP_EXIT reply message to kill staprun */
+ {} /* await STP_EXIT reply message to kill staprun */
}
/* If the runtime does not implement select() on the command
if (nb >= 0 || (errno != EINTR && errno != EAGAIN)) {
_perr(_("Unexpected EOF in read (nb=%ld)"), (long)nb);
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
}
if (!select_supported) {
{
_perr(_("Unexpected error in select"));
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
}
}
continue;
if (write_realtime_data(recvbuf.payload.data, nb)) {
_perr(_("write error (nb=%ld)"), (long)nb);
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
}
break;
#endif
dbug(2, "got STP_EXIT\n");
if (monitor)
monitor_exited();
- else
+ else {
cleanup_and_exit(0, error_detected);
+ /* NOTREACHED */
+ }
/* monitor mode exit handled elsewhere, later. */
break;
}
if (target_cmd)
kill(target_pid, SIGKILL);
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
} else if (target_cmd) {
dbug(1, "detaching pid %d\n", target_pid);
#if WORKAROUND_BZ467568
if (target_cmd)
kill(target_pid, SIGKILL);
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
}
#endif
}
struct _stp_msg_start ts;
struct _stp_msg_ns_pid nspid;
if (use_old_transport) {
- if (init_oldrelayfs() < 0)
+ if (init_oldrelayfs() < 0) {
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
+ }
} else {
if (init_relayfs() < 0)
cleanup_and_exit(0, 1);
+ /* NOTREACHED */
}
if (target_namespaces_pid > 0) {
nspid.target = target_namespaces_pid;
rc = send_request(STP_NAMESPACES_PID, &nspid, sizeof(nspid));
if (rc != 0) {
- perror ("Unable to send STP_NAMESPACES_PID");
- cleanup_and_exit (1, rc);
- }
+ perror ("Unable to send STP_NAMESPACES_PID");
+ cleanup_and_exit (1, rc);
+ /* NOTREACHED */
+ }
}
ts.target = target_pid;
if (rc != 0) {
perror ("Unable to send STP_START");
cleanup_and_exit(0, rc);
+ /* NOTREACHED */
}
- if (load_only)
+ if (load_only) {
cleanup_and_exit(1, 0);
+ /* NOTREACHED */
+ }
break;
}
default:
--- /dev/null
+set test "attach_detach"
+if {![installtest_p]} { untested $test; return }
+
+set test_script { "
+ probe begin { printf(\"begin probe fired\\n\") }
+ probe timer.s(5) { printf(\"timer probe fired\\n\") }
+ probe end { printf(\"end probe fired\\n\") }
+" }
+
+# First, compile a module.
+stap_compile $test 1 $test_script -m attach_detach
+
+# stap_compile does pass/fail, but doesn't return a status. So, if
+# attach_detach.ko exists, it worked.
+if {! [file exists attach_detach.ko]} {
+ return
+}
+
+# Load the module and detach.
+set subtest "initial load"
+spawn staprun -L attach_detach.ko
+set fail 0
+set pass 0
+expect {
+ -timeout 120
+ -re "^begin probe fired\r\n" { incr fail; exp_continue }
+ -re "^\r\n" { exp_continue }
+ -re "^Disconnecting from systemtap module.\r\n" {
+ incr pass; exp_continue
+ }
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
+ incr pass
+ }
+ eof { fail "$test ($subtest) - EOF"; incr fail }
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
+}
+catch {close}; catch {wait}
+
+if {$fail == 0 && $pass == 2} {
+ pass "$test ($subtest) - disconnect seen"
+} else {
+ fail "$test ($subtest) - begin seen ($fail $pass)"
+}
+
+# Make sure the module is still loaded.
+if {[catch { exec lsmod | grep attach_detach >/dev/null }]} {
+ fail "$test ($subtest) - module still present"
+ return
+}
+pass "$test ($subtest) - module still present"
+
+# Attach to the module, then use SIGQUIT to detach again.
+set subtest "attach and SIGQUIT"
+spawn staprun -A attach_detach
+set fail 0
+set pass 0
+set timer_probe_seen 0
+expect {
+ -timeout 120
+ -re "^begin probe fired\r\n" { incr pass; exp_continue }
+ -re "^end probe fired\r\n" { incr fail; exp_continue }
+ -re "^timer probe fired\r\n" {
+ if {!$timer_probe_seen} {
+ set timer_probe_seen 1
+ incr pass
+
+ # Send our staprun process a SIGQUIT, to make it detach.
+ kill SIGQUIT [exp_pid]
+ }
+ exp_continue
+ }
+ -re "^\r\n" { exp_continue }
+ -re "^Disconnecting from systemtap module.\r\n" {
+ incr pass; exp_continue
+ }
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
+ incr pass
+ }
+ eof { fail "$test ($subtest) - EOF"; incr fail }
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
+}
+catch {close}; catch {wait}
+
+if {$fail == 0 && $pass == 4} {
+ pass "$test ($subtest) - disconnect seen"
+} else {
+ fail "$test ($subtest) - no disconnect seen ($fail $pass)"
+}
+
+# Make sure the module is still loaded.
+if {[catch { exec lsmod | grep attach_detach >/dev/null}]} {
+ fail "$test ($subtest) - module still present"
+ return
+}
+pass "$test ($subtest) - module still present"
+
+# Attach one last time, then use SIGTERM to unload the module and quit.
+set subtest "attach and SIGTERM"
+spawn staprun -A attach_detach
+set fail 0
+set pass 0
+set timer_probe_seen 0
+expect {
+ -timeout 120
+ -re "^begin probe fired\r\n" { incr fail; exp_continue }
+ -re "^end probe fired\r\n" { incr pass }
+ -re "^timer probe fired\r\n" {
+ if {!$timer_probe_seen} {
+ set timer_probe_seen 1
+ incr pass
+
+ # Send our staprun process a SIGTERM, to make it quit and
+ # unload.
+ kill SIGTERM [exp_pid]
+ }
+ exp_continue
+ }
+ -re "^\r\n" { exp_continue }
+ -re "^Disconnecting from systemtap module.\r\n" {
+ incr fail; exp_continue
+ }
+ -re "^To reconnect, type \"staprun -A attach_detach\"\r\n" {
+ incr fail; exp_continue
+ }
+ eof { fail "$test ($subtest) - EOF"; incr fail }
+ timeout { fail "$test ($subtest) - unexpected timeout"; incr fail }
+}
+catch {close}; catch {wait}
+
+if {$fail == 0 && $pass == 2} {
+ pass "$test ($subtest) - quit seen"
+} else {
+ fail "$test ($subtest) - no quit seen ($fail $pass)"
+}
+
+# Make sure the module isn't still loaded.
+if {[catch { exec lsmod | grep attach_detach >/dev/null}]} {
+ pass "$test ($subtest) - module is gone"
+} else {
+ fail "$test ($subtest) - module is gone"
+
+ # If for some odd reason the module is still loaded, try to unload
+ # it.
+ catch { exec staprun -d attach_detach }
+}