This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCH] Fix bug of signal.stp
- From: Lai Jiangshan <laijs at cn dot fujitsu dot com>
- To: systemtap at sourceware dot org
- Date: Thu, 15 Nov 2007 09:50:34 +0800
- Subject: [PATCH] Fix bug of signal.stp
Hi, all
There are some problems with si_code in signal.send and signal.checkperm.
First, test a pointer whether it's negative does not make any sense.
So the si_code can not be correct.
-----old code--------
if (sinfo == 2)
si_code ="SIGSTOP or SIGKILL"
else if (sinfo > 0)
si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
else if (sinfo <= 0)
si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
---------------------
Second, si_code should be the value of info->si_code. If not,
it will make user confused.
In my patch, 2 variables are added and another one modified:
si_code is the value of info->si_code, indicates why this signal was sent.
si_code_name is a string representation of the si_code.
sig_type is new name for old si_code, indicates the signal type.
and 2 functions are added:
__get_sigqueue_info - get addr of info from struct sigqueue
signal_si_code_name - figure out si_code_name from sig and si_code
Patch:
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
--- systemtap-20071110/tapset/signal.stp 2007-09-26 10:10:43.000000000 +0800
+++ tapset/signal.stp 2007-11-12 07:00:35.000000000 +0800
@@ -27,7 +27,9 @@
* sig_name - a string representation of the signal
* sig_pid - pid of the signal recipient process
* pid_name - name of the signal recipient process
- * si_code - indicates the signal type.
+ * si_code - indicates why this signal was sent. See sigaction(2).
+ * si_code_name - a string representation of the si_code.
+ * sig_type - indicates the signal type.
* task - a task handle to the signal recipient
* sinfo - the address of siginfo struct.
* shared - indicates whether this signal is shared by the thread group
@@ -40,13 +42,15 @@ probe signal.send = _signal.send.*
sig_name = _signal_name($sig)
sig_pid = task_pid(task)
pid_name = task_execname(task)
+ si_code_name = signal_si_code_name(sig, si_code)
if (sinfo == 2)
- si_code ="SIGSTOP or SIGKILL"
- else if (sinfo > 0)
- si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
- else if (sinfo <= 0)
- si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
+ sig_type = "SIGSTOP or SIGKILL"
+ else if (si_code > 0)
+ sig_type = "SI_KERNEL (SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGCHLD, SIGPOLL)"
+ else if (si_code <= 0)
+ sig_type = si_code_name # SI_USER, SI_QUEUE, SI_TIMER, SI_MESGQ,
+ # SI_ASYNCIO, SI_SIGIO, SI_TKILL, SI_DETHREAD
}
probe _signal.send.part1 = kernel.function("__group_send_sig_info")
@@ -54,6 +58,12 @@ probe _signal.send.part1 = kernel.functi
name = "__group_send_sig_info"
task = $p
sinfo = $info
+ if (sinfo == 1) # SEND_SIG_PRIV, when signal is delivered, si_code is
+ si_code = 0x80 # SI_KERNEL
+ else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+ si_code = 0 # SI_USER, but signo is SIGSTOP or SIGKILL
+ else
+ si_code = $info->si_code
shared = 1
send2queue = 0
}
@@ -62,7 +72,8 @@ probe _signal.send.part2 = kernel.functi
{
name = "send_group_sigqueue"
task = $p
- # sinfo = $q->info
+ sinfo = __get_sigqueue_info($q)
+ si_code = $q->info->si_code
shared = 1
send2queue = 1
}
@@ -71,7 +82,8 @@ probe _signal.send.part3 = kernel.functi
{
name = "send_sigqueue"
task = $p
- # sinfo = $q->info
+ sinfo = __get_sigqueue_info($q)
+ si_code = $q->info->si_code
shared = 0
send2queue = 1
}
@@ -81,10 +93,21 @@ probe _signal.send.part4 = kernel.functi
name = "specific_send_sig_info"
task = $t
sinfo = $info
+ if (sinfo == 1) # SEND_SIG_PRIV, when signal is delivered, si_code is
+ si_code = 0x80 # SI_KERNEL
+ else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+ si_code = 0 # SI_USER, but signo is SIGSTOP or SIGKILL
+ else
+ si_code = $info->si_code
shared = 0
send2queue = 0
}
+function __get_sigqueue_info:long(q:long) %{
+ struct sigqueue *q = (struct sigqueue *)((long)THIS->q);
+ THIS->__retvalue = (uint64_t)(&q->info);
+%}
+
/* probe signal.send.return
*/
probe signal.send.return = _signal.send.*.return
@@ -170,12 +193,21 @@ probe signal.checkperm = kernel.function
sig_pid = task_pid(task)
pid_name = task_execname(task)
+ if (sinfo == 1) # SEND_SIG_PRIV, when signal is delivered, si_code is
+ si_code = 0x80 # SI_KERNEL
+ else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+ si_code = 0 # SI_USER, but signo is SIGSTOP or SIGKILL
+ else
+ si_code = $info->si_code
+ si_code_name = signal_si_code_name(sig, si_code)
+
if (sinfo == 2)
- si_code ="SIGSTOP or SIGKILL"
- else if (sinfo > 0)
- si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
- else if (sinfo <= 0)
- si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
+ sig_type = "SIGSTOP or SIGKILL"
+ else if (si_code > 0)
+ sig_type = "SI_KERNEL (SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGCHLD, SIGPOLL)"
+ else if (si_code <= 0)
+ sig_type = si_code_name # SI_USER, SI_QUEUE, SI_TIMER, SI_MESGQ,
+ # SI_ASYNCIO, SI_SIGIO, SI_TKILL, SI_DETHREAD
}
probe signal.checkperm.return = kernel.function("check_kill_permission").return
@@ -493,3 +525,105 @@ probe signal.flush = kernel.function("fl
sig_pid = $t->pid
pid_name = kernel_string($t->comm)
}
+
+function signal_si_code_name:string(sig:long, si_code:long)
+%{ /* pure */
+ int sig = (int)THIS->sig;
+ int si_code = (int)THIS->si_code;
+ const char *si_code_name = NULL;
+ switch(si_code) {
+ case SI_USER: si_code_name = "SI_USER"; break;
+ case SI_KERNEL: si_code_name = "SI_KERNEL"; break;
+ case SI_QUEUE: si_code_name = "SI_QUEUE"; break;
+ case SI_TIMER: si_code_name = "SI_TIMER"; break;
+ case SI_MESGQ: si_code_name = "SI_MESGQ"; break;
+ case SI_ASYNCIO: si_code_name = "SI_ASYNCIO"; break;
+ case SI_SIGIO: si_code_name = "SI_SIGIO"; break;
+ case SI_TKILL: si_code_name = "SI_TKILL"; break;
+ case SI_DETHREAD:si_code_name = "SI_DETHREAD"; break;
+ default:break;
+ }
+ if (si_code_name != NULL) {
+ strlcpy (THIS->__retvalue, si_code_name, MAXSTRINGLEN);
+ return;
+ }
+ switch(sig) {
+ default:break;
+ case SIGILL:
+ switch(si_code){
+ case ILL_ILLOPC:si_code_name = "ILL_ILLOPC"; break;
+ case ILL_ILLOPN:si_code_name = "ILL_ILLOPN"; break;
+ case ILL_ILLADR:si_code_name = "ILL_ILLADR"; break;
+ case ILL_ILLTRP:si_code_name = "ILL_ILLTRP"; break;
+ case ILL_PRVOPC:si_code_name = "ILL_PRVOPC"; break;
+ case ILL_PRVREG:si_code_name = "ILL_PRVREG"; break;
+ case ILL_COPROC:si_code_name = "ILL_COPROC"; break;
+ case ILL_BADSTK:si_code_name = "ILL_BADSTK"; break;
+ default:break;
+ }
+ break;
+ case SIGFPE:
+ switch(si_code){
+ case FPE_INTDIV:si_code_name = "FPE_INTDIV"; break;
+ case FPE_INTOVF:si_code_name = "FPE_INTOVF"; break;
+ case FPE_FLTDIV:si_code_name = "FPE_FLTDIV"; break;
+ case FPE_FLTOVF:si_code_name = "FPE_FLTOVF"; break;
+ case FPE_FLTUND:si_code_name = "FPE_FLTUND"; break;
+ case FPE_FLTRES:si_code_name = "FPE_FLTRES"; break;
+ case FPE_FLTINV:si_code_name = "FPE_FLTINV"; break;
+ case FPE_FLTSUB:si_code_name = "FPE_FLTSUB"; break;
+ default:break;
+ }
+ break;
+ case SIGSEGV:
+ switch(si_code){
+ case SEGV_MAPERR:si_code_name = "SEGV_MAPERR"; break;
+ case SEGV_ACCERR:si_code_name = "SEGV_ACCERR"; break;
+ default:break;
+ }
+ break;
+ case SIGBUS:
+ switch(si_code){
+ case BUS_ADRALN:si_code_name = "BUS_ADRALN"; break;
+ case BUS_ADRERR:si_code_name = "BUS_ADRERR"; break;
+ case BUS_OBJERR:si_code_name = "BUS_OBJERR"; break;
+ default:break;
+ }
+ break;
+ case SIGTRAP:
+ switch(si_code){
+ case TRAP_BRKPT:si_code_name = "TRAP_BRKPT"; break;
+ case TRAP_TRACE:si_code_name = "TRAP_TRACE"; break;
+ default:break;
+ }
+ break;
+ case SIGCHLD:
+ switch(si_code){
+ case CLD_EXITED :si_code_name = "CLD_EXITED"; break;
+ case CLD_KILLED :si_code_name = "CLD_KILLED"; break;
+ case CLD_DUMPED :si_code_name = "CLD_DUMPED"; break;
+ case CLD_TRAPPED :si_code_name = "CLD_TRAPPED"; break;
+ case CLD_STOPPED :si_code_name = "CLD_STOPPED"; break;
+ case CLD_CONTINUED:si_code_name = "CLD_CONTINUED"; break;
+ default:break;
+ }
+ break;
+ case SIGPOLL:
+ switch(si_code){
+ case POLL_IN :si_code_name = "POLL_IN "; break;
+ case POLL_OUT:si_code_name = "POLL_OUT"; break;
+ case POLL_MSG:si_code_name = "POLL_MSG"; break;
+ case POLL_ERR:si_code_name = "POLL_ERR"; break;
+ case POLL_PRI:si_code_name = "POLL_PRI"; break;
+ case POLL_HUP:si_code_name = "POLL_HUP"; break;
+ default:break;
+ }
+ break;
+ }
+ if (si_code_name != NULL) {
+ strlcpy (THIS->__retvalue, si_code_name, MAXSTRINGLEN);
+ } else {
+ strlcpy (THIS->__retvalue, "UNKNOWN", MAXSTRINGLEN);
+ }
+%}
+