#! /bin/sh //bin/true && exec stap -DMAXACTION=10000 -g $0 ${1+"$@"} # psig # Copyright (C) 2008-2012 Red Hat, Inc., Eugene Teo # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # psig reports information about signals by the process id. # # psig is not a port of Solaris' psig tool. It was written based on the example # output at http://developers.sun.com/solaris/articles/solaris_linux_app.html. # This script requires the signal.stp-psig.patch for tapset/signal.stp (not in # the upstream version of SystemTap at the time of writing). # # $ psig $$ | head -10 # 1852: bash # HUP caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # INT caught 0x0808d280 0 # QUIT ignored # ILL caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # TRAP caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # ABRT caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # BUS caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # FPE caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,FPE,USR1,SEGV,USR2,PIPE,ALRM,TERM,XCPU,XFSZ,VTALRM,SYS # KILL default # $ stap -V # systemtap-20071229.tar.bz2 # SystemTap translator/driver (version 0.6/0.131 built 2008-01-12) # $ cat /etc/redhat-release # Fedora release 8 (Werewolf) # $ uname -a # Linux kerndev.xxx.redhat.com 2.6.23.9-85.fc8 #1 SMP Fri Dec 7 15:49:59 EST 2007 i686 i686 i386 GNU/Linux # # NOTES: # HUP caught 0x0808d040 0 HUP,INT,ILL,TRAP,ABRT,BUS,... # [.......][.......][..........][.][............................ # |<-- type of signal (1..64) # |<-- signal disposition. it can be SIG_{DFL,IGN,ERR} or a pointer to a function # |<-- address of the signal-catching function # |<-- sa_flags. see the code snippet below # |<-- set of signals to be blocked when executing the handler # # linux-2.6/include/asm-x86/signal.h: # [...] # /* # * SA_FLAGS values: # * # * SA_ONSTACK indicates that a registered stack_t will be used. # * SA_RESTART flag to get restarting signals (which were the default long ago) # * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. # * SA_RESETHAND clears the handler when the signal is delivered. # * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. # * SA_NODEFER prevents the current signal from being masked in the handler. # * # * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single # * Unix names RESETHAND and NODEFER respectively. # */ # #define SA_NOCLDSTOP 0x00000001u # #define SA_NOCLDWAIT 0x00000002u # #define SA_SIGINFO 0x00000004u # #define SA_ONSTACK 0x08000000u # #define SA_RESTART 0x10000000u # #define SA_NODEFER 0x40000000u # #define SA_RESETHAND 0x80000000u # # #define SA_NOMASK SA_NODEFER # #define SA_ONESHOT SA_RESETHAND # # #define SA_RESTORER 0x04000000 # global _NSIG = 64 function get_k_sigaction:long (task:long, sig:long) %{ struct task_struct *p = (struct task_struct *)((long)STAP_ARG_task); STAP_RETVALUE = (long)&p->sighand->action[(int)STAP_ARG_sig]; %} function get_task_info:string (task:long) %{ char pid[10]; /* just to realign the header properly */ struct task_struct *p = (struct task_struct *)((long)STAP_ARG_task); if (!p) strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { sprintf(pid, "%d:", p->pid); snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%-8s %s", pid, p->comm); } %} function translate_mask:string (mask:string) { str = signal_str(strtol(tokenize(mask, ","), 10)) while (1) { sig = signal_str(strtol(tokenize("", ","), 10)) if (strlen(sig) == 0) break; str = str . "," . sig } return str; } /* * if sa_flags is 0, then return 0. If not, return the interpreted sa_flags. */ function sa_flags_str2:string (sa_flags:string) %{ if (strlen(STAP_ARG_sa_flags) == 0) strcpy(STAP_ARG_sa_flags, "0"); strlcpy (STAP_RETVALUE, STAP_ARG_sa_flags, MAXSTRINGLEN); %} probe begin { %( $# < 1 %? pid = target() %: pid = $1 %) # if (pid == 0) error ("Please provide valid target process-id as $1 or -x PID"); task = pid2task(pid) assert(task, "pid2task: process not found. exiting.\n") task_info = get_task_info(task) assert(!isinstr(task_info, "NULL"), "get_task_info: invalid task_struct. exiting.\n") printf("%s\n", task_info) for (i = 0; i < _NSIG; ++i) { handler_status = "" act = get_k_sigaction(task, i) assert(act, "get_k_sigaction: invalid k_sigaction pointer. exiting.\n") sig = signal_str(i+1) handler = sa_handler_str(get_sa_handler(act)) # XXX: convert hex pointer via usymdata() to useful function if (! (isinstr(handler, "default") || isinstr(handler, "ignored"))) { blocked = is_sig_blocked(task, i+1) if (blocked) handler_status = "blocked," handler_status = handler_status . "caught" } else handler_status = handler flags = sa_flags_str2(sa_flags_str(get_sa_flags(act))) mask = sigset_mask_str(get_sigaction_mask(act)) printf("%-8s %-8s ", sig, handler_status); if (isinstr(handler_status, "caught")) printf("%s %s %s\n", handler, flags, translate_mask(mask)) else printf("\n") } exit() }