summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/transport/transport.c38
-rw-r--r--tapsets.cxx25
-rw-r--r--testsuite/systemtap.base/pr10854.exp32
-rw-r--r--testsuite/systemtap.base/pr10854.stp20
4 files changed, 94 insertions, 21 deletions
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index f5efce9f..bab5efa9 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -19,6 +19,7 @@
#include <linux/namei.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
static int _stp_exit_flag = 0;
@@ -30,6 +31,9 @@ static int _stp_ctl_attached = 0;
static pid_t _stp_target = 0;
static int _stp_probes_started = 0;
+static int _stp_exit_called = 0;
+static DEFINE_MUTEX(_stp_transport_mutex);
+
// For now, disable transport version 3 (unless STP_USE_RING_BUFFER is
// defined).
@@ -81,22 +85,26 @@ static struct workqueue_struct *_stp_wq;
static void _stp_handle_start(struct _stp_msg_start *st)
{
- dbug_trans(1, "stp_handle_start\n");
+ mutex_lock(&_stp_transport_mutex);
+ if (!_stp_exit_called) {
+ dbug_trans(1, "stp_handle_start\n");
#ifdef STAPCONF_VM_AREA
- { /* PR9740: workaround for kernel valloc bug. */
- void *dummy;
- dummy = alloc_vm_area (PAGE_SIZE);
- free_vm_area (dummy);
- }
+ { /* PR9740: workaround for kernel valloc bug. */
+ void *dummy;
+ dummy = alloc_vm_area (PAGE_SIZE);
+ free_vm_area (dummy);
+ }
#endif
- _stp_target = st->target;
- st->res = probe_start();
- if (st->res >= 0)
- _stp_probes_started = 1;
+ _stp_target = st->target;
+ st->res = probe_start();
+ if (st->res >= 0)
+ _stp_probes_started = 1;
- _stp_ctl_send(STP_START, st, sizeof(*st));
+ _stp_ctl_send(STP_START, st, sizeof(*st));
+ }
+ mutex_unlock(&_stp_transport_mutex);
}
/* common cleanup code. */
@@ -106,8 +114,7 @@ static void _stp_handle_start(struct _stp_msg_start *st)
/* when someone does /sbin/rmmod on a loaded systemtap module. */
static void _stp_cleanup_and_exit(int send_exit)
{
- static int _stp_exit_called = 0;
-
+ mutex_lock(&_stp_transport_mutex);
if (!_stp_exit_called) {
int failures;
@@ -135,6 +142,7 @@ static void _stp_cleanup_and_exit(int send_exit)
_stp_ctl_send(STP_EXIT, NULL, 0);
dbug_trans(1, "done with ctl_send STP_EXIT\n");
}
+ mutex_unlock(&_stp_transport_mutex);
}
static void _stp_request_exit(void)
@@ -293,7 +301,7 @@ err0:
static inline void _stp_lock_inode(struct inode *inode)
{
-#ifdef DEFINE_MUTEX
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
mutex_lock(&inode->i_mutex);
#else
down(&inode->i_sem);
@@ -302,7 +310,7 @@ static inline void _stp_lock_inode(struct inode *inode)
static inline void _stp_unlock_inode(struct inode *inode)
{
-#ifdef DEFINE_MUTEX
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
mutex_unlock(&inode->i_mutex);
#else
up(&inode->i_sem);
diff --git a/tapsets.cxx b/tapsets.cxx
index 17e6c6cf..31d162a2 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -326,6 +326,7 @@ function_spec_type
struct dwarf_builder;
+struct dwarf_var_expanding_visitor;
// XXX: This class is a candidate for subclassing to separate
@@ -377,7 +378,7 @@ protected:
private:
string args;
- void saveargs(dwarf_query& q, Dwarf_Die* scope_die);
+ void saveargs(dwarf_query& q, Dwarf_Die* scope_die, dwarf_var_expanding_visitor& v);
};
@@ -2813,12 +2814,13 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
q.has_call = false;
q.base_probe->body = old_body;
}
+ // Save the local variables for listing mode
+ if (q.sess.listing_mode_vars)
+ saveargs(q, scope_die, v);
}
// else - null scope_die - $target variables will produce an error during translate phase
- // Save the local variables for listing mode
- if (q.sess.listing_mode_vars)
- saveargs(q, scope_die);
+ // PR10820: null scope die, local variables aren't accessible, not necessary to invoke saveargs
// Reset the sole element of the "locations" vector as a
// "reverse-engineered" form of the incoming (q.base_loc) probe
@@ -2885,7 +2887,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
void
-dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die)
+dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die, dwarf_var_expanding_visitor& v)
{
if (null_die(scope_die))
return;
@@ -2923,7 +2925,18 @@ dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die)
!dwarf_type_name(&type_die, type_name))
continue;
- argstream << " $" << arg_name << ":" << type_name;
+ /* trick from visit_target_symbol_context */
+ target_symbol *tsym = new target_symbol;
+ token *t = new token;
+ tsym->tok = t;
+ tsym->base_name = "$";
+ tsym->base_name += arg_name;
+
+ /* Ignore any variable that isn't accessible */
+ tsym->saved_conversion_error = 0;
+ v.require (tsym);
+ if (!tsym->saved_conversion_error)
+ argstream << " $" << arg_name << ":" << type_name;
}
while (dwarf_siblingof (&arg, &arg) == 0);
diff --git a/testsuite/systemtap.base/pr10854.exp b/testsuite/systemtap.base/pr10854.exp
new file mode 100644
index 00000000..9173c8b4
--- /dev/null
+++ b/testsuite/systemtap.base/pr10854.exp
@@ -0,0 +1,32 @@
+# This test is to make sure that we've resolved PR10854's race between probe
+# initialization and shutdown. Here we load a module and then kill the stapio
+# process as soon as we can to try to make the init and shutdown overlap.
+
+set test "pr10854"
+
+# precompile the script module
+set compile { exec stap $srcdir/$subdir/$test.stp sys_read *@fs/*.c -p4 }
+if { [catch { set module [eval $compile] } msg ] } {
+ fail "compiling $test.stp: $msg"
+ untested "$test runloop"
+ continue
+} else {
+ pass "compiling $test.stp"
+}
+
+if {![installtest_p]} {
+ untested "$test runloop"
+ continue
+}
+
+# run & kill the module 10 times
+# (this was usually enough to trigger the fault)
+for {set i 0} {$i < 10} {incr i} {
+ spawn staprun $module -o /dev/null
+ while { [catch { exec pkill stapio -P [pid] } msg ] } { }
+ catch { close }
+ wait
+}
+
+# if we're still alive, we pass :)
+pass "$test runloop"
diff --git a/testsuite/systemtap.base/pr10854.stp b/testsuite/systemtap.base/pr10854.stp
new file mode 100644
index 00000000..55f027f2
--- /dev/null
+++ b/testsuite/systemtap.base/pr10854.stp
@@ -0,0 +1,20 @@
+function trace(entry_p) {
+ if(tid() in trace)
+ printf("%s%s%s\n",thread_indent(entry_p),
+ (entry_p>0?"->":"<-"),
+ probefunc())
+}
+
+global trace
+probe kernel.function(@1).call {
+ if (execname() == "staprun") next # skip our own helper process
+ trace[tid()] = 1
+ trace(1)
+}
+probe kernel.function(@1).return {
+ trace(-1)
+ delete trace[tid()]
+}
+
+probe kernel.function(@2).call { trace(1) }
+probe kernel.function(@2).return { trace(-1) }