diff options
-rw-r--r-- | runtime/transport/transport.c | 38 | ||||
-rw-r--r-- | tapsets.cxx | 25 | ||||
-rw-r--r-- | testsuite/systemtap.base/pr10854.exp | 32 | ||||
-rw-r--r-- | testsuite/systemtap.base/pr10854.stp | 20 |
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) } |