Blame SOURCES/rhbz1527809.patch

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
+}