On Wed, Mar 27, 2013 at 9:48 PM, Irek Szczesniak <[email protected]> wrote:
> On Wed, Mar 27, 2013 at 6:10 PM, Roland Mainz <[email protected]>
> wrote:
>> On Wed, Mar 27, 2013 at 11:31 AM, Irek Szczesniak <[email protected]>
>> wrote:
>> [snip]
>>>>> BTW: The patch currently doesn't cover passing SIGCHLD siginfo data to
>>>>> the shell traps (this needs to be done in |job_waitsafe()| ... but
>>>>> that may be tricky).
>>>>
>>>> Could you add.sh.status (Exit value or signal) and .sh.pid for CHLD
>>>> traps, please?
>>>
>>> Appending to this RFE:
>>> We like to have .sh.code for CHLD traps too, with .sh.code being a
>>> STRING returning one of the CLD_* codes defined in
>>> http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html (i.e.
>>> this is defined by X/OPEN and POSIX and therefore should be applicable
>>> as shell extension).
>>
>> Erm... do you mean that you want to be able to write a ksh93 version
>> of the following C code ?
>> -- snip --
>> #include <stdlib.h>
>> #include <stdio.h>
>> #include <signal.h>
>> #include <sys/types.h>
>> #include <unistd.h>
>> #include <errno.h>
>>
>> static
>> const char *sicode2str(int si_code)
>> {
>> const char *str;
>> switch(si_code)
>> {
>> #define STRSYM(sym) \
>> case (sym): str = #sym ; break;
>> STRSYM(CLD_EXITED)
>> STRSYM(CLD_KILLED)
>> STRSYM(CLD_DUMPED)
>> STRSYM(CLD_TRAPPED)
>> STRSYM(CLD_STOPPED)
>> STRSYM(CLD_CONTINUED)
>> default:
>> str="<unknown>";
>> break;
>> }
>> return str;
>> }
>>
>>
>> static
>> void chld_handler (int signum, siginfo_t *si,
>> void *context)
>> {
>> printf("#SIGCHLD, si_code=%d/%s handler\n",
>> si->si_code,
>> sicode2str(si->si_code));
>> }
>>
>>
>> static
>> void chsleep(void)
>> {
>> int i;
>> for (i=0 ; i < 120 ; i++)
>> usleep(10000);
>> }
>>
>>
>> int main(int ac, char *av[])
>> {
>> struct sigaction new_action;
>> pid_t pid;
>>
>> /* Setting-up the sigchld handler */
>> new_action.sa_sigaction = chld_handler;
>> sigemptyset (&new_action.sa_mask);
>> new_action.sa_flags = SA_SIGINFO;
>> sigaction (SIGCHLD, &new_action, NULL);
>>
>> pid = fork(); /*FIXME: Need error handling*/
>>
>> if (pid == 0)
>> {
>> /* Child process */
>>
>> puts("# child process "
>> "(stopping now...)");
>> raise(SIGSTOP);
>>
>> puts("# child continues...");
>>
>> _exit(0);
>> }
>> else
>> {
>> /* Parent process */
>>
>> chsleep();
>> puts("# parent waking child...");
>> kill(pid, SIGCONT);
>> chsleep();
>> }
>>
>> return EXIT_SUCCESS;
>> }
>> -- snip --
>>
>> The output should look like this:
>> -- snip --
>> # child process (stopping now...)
>> #SIGCHLD, si_code=5/CLD_STOPPED handler
>> # parent waking child...
>> # child continues...
>> #SIGCHLD, si_code=6/CLD_CONTINUED handler
>> #SIGCHLD, si_code=1/CLD_EXITED handler
>> -- snip --
>>
>> This should be technically possible to implement in ksh93... but for
>> which purpose are you interested in the |CLD_STOPPED|&co. codes ?
>
> Until now there is no scalable way to monitor only a single process in
> a pool of many (20000+) worker processes. The usual way of listening
> to the CHLD trap and then take a sample of the job list using jobs -l
> works but scales very poorly. Using the information solely from the
> siginfo data passed to the CHLD handler would avoid that scalability
> bottleneck.
> Looking at si_code reveals whether the child process completed
> successfully, crashed or somehow else changed state and is thus IMO
> mandatory to replace jobs -l as information source.
Ok... thanks for the explanation.
Attached (as "astksh20130318_shsig_chld001.diff.txt") is a dumb 10min
hack which fills the .sh.sig data for CHLD traps.
* Changes:
- .sh.sig data are now filled for CHLD traps
- ".sh.sig.name" was renamed to ".sh.sig.signame" to avoid naming
collisions on platforms which pass names around as part of |siginfo_t|
- ".sh.sig.code" is now a _string_ since |siginfo_t|'s |si_code|
numbers are not portable... nor are they self-explaining (the strings
returned should be...)
- .sh.sig.status now works and returns even exit codes like 97 or 121 ...
* Open issues:
- ".sh.sig.code" code should be more robust (SIGRT* signals come in mind)
- .sh.sig.* should only have variables available which match the
siginfo_t data returned
- Only |CLD_EXITED| is currently supported since the code is mostly a
10min hack... the real code should save the |siginfo_t| data in a list
and replay it when the CHLD shell traps are called.
* Example usage looks like this:
-- snip --
$ cat test1.sh
function chld_trap
{
printf "child done, code=%q, exit code=%d\n" \
"${.sh.sig.code}" \
${.sh.sig.status}
}
trap 'chld_trap' CHLD
exit 120 &
wait
print '#done.'
$ ksh ./test1.sh
child done, code=CLD_EXITED, exit code=120
#done.
-- snip --
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) [email protected]
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
diff -r -u build_i386_64bit_debug_unpatched/src/cmd/ksh93/data/variables.c
build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/data/variables.c
--- build_i386_64bit_debug_unpatched/src/cmd/ksh93/data/variables.c
2012-10-01 18:58:22.000000000 +0200
+++ build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/data/variables.c
2013-03-29 15:15:02.717053517 +0100
@@ -118,11 +118,11 @@
const Shtable_t shtab_siginfo[] =
{
"signo", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
- "name", NV_RDONLY|NV_MINIMAL|NV_NOFREE,
+ "signame", NV_RDONLY|NV_MINIMAL|NV_NOFREE,
"pid", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
"uid", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
"value", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER|NV_LONG,
- "code", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
+ "code", NV_RDONLY|NV_MINIMAL|NV_NOFREE,
"status", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
"errno", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER,
"addr", NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER|NV_LONG,
diff -r -u build_i386_64bit_debug_unpatched/src/cmd/ksh93/sh/init.c
build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/sh/init.c
--- build_i386_64bit_debug_unpatched/src/cmd/ksh93/sh/init.c 2013-03-11
21:45:45.000000000 +0100
+++ build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/sh/init.c
2013-03-29 15:31:44.253142901 +0100
@@ -2040,6 +2040,117 @@
svar_init(shp,SH_SIG,shtab_siginfo);
}
+const char *siginfocode2name(Shell_t *shp, int signo, int sicode)
+{
+ const char *str = NULL;
+#define SYM2STR(sym) case sym: str = #sym ; break ;
+ switch(signo)
+ {
+ case SIGILL:
+ switch(sicode)
+ {
+ SYM2STR(ILL_ILLOPC)
+ SYM2STR(ILL_ILLOPN)
+ SYM2STR(ILL_ILLADR)
+ SYM2STR(ILL_ILLTRP)
+ SYM2STR(ILL_PRVOPC)
+ SYM2STR(ILL_PRVREG)
+ SYM2STR(ILL_COPROC)
+ SYM2STR(ILL_BADSTK)
+ default:
+ sfprintf(shp->strbuf, "<SIGILL-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGFPE:
+ switch(sicode)
+ {
+ SYM2STR(FPE_INTDIV)
+ SYM2STR(FPE_INTOVF)
+ SYM2STR(FPE_FLTDIV)
+ SYM2STR(FPE_FLTOVF)
+ SYM2STR(FPE_FLTUND)
+ SYM2STR(FPE_FLTRES)
+ SYM2STR(FPE_FLTINV)
+ SYM2STR(FPE_FLTSUB)
+ default:
+ sfprintf(shp->strbuf, "<SIGFPE-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGSEGV:
+ switch(sicode)
+ {
+ SYM2STR(SEGV_MAPERR)
+ SYM2STR(SEGV_ACCERR)
+ default:
+ sfprintf(shp->strbuf, "<SIGSEGV-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGBUS:
+ switch(sicode)
+ {
+ SYM2STR(BUS_ADRALN)
+ SYM2STR(BUS_ADRERR)
+ SYM2STR(BUS_OBJERR)
+ default:
+ sfprintf(shp->strbuf, "<SIGBUS-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGTRAP:
+ switch(sicode)
+ {
+ SYM2STR(TRAP_BRKPT)
+ SYM2STR(TRAP_TRACE)
+ default:
+ sfprintf(shp->strbuf, "<SIGTRAP-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGCHLD:
+ switch(sicode)
+ {
+ SYM2STR(CLD_EXITED)
+ SYM2STR(CLD_KILLED)
+ SYM2STR(CLD_DUMPED)
+ SYM2STR(CLD_TRAPPED)
+ SYM2STR(CLD_STOPPED)
+ SYM2STR(CLD_CONTINUED)
+ default:
+ sfprintf(shp->strbuf, "<SIGCHLD-code%x>",
sicode);
+ break;
+ }
+ break;
+ case SIGPOLL:
+ switch(sicode)
+ {
+ SYM2STR(POLL_IN)
+ SYM2STR(POLL_OUT)
+ SYM2STR(POLL_MSG)
+ SYM2STR(POLL_ERR)
+ SYM2STR(POLL_PRI)
+ SYM2STR(POLL_HUP)
+ default:
+ sfprintf(shp->strbuf, "<SIGPOLL-code%x>",
sicode);
+ break;
+ }
+ break;
+ default:
+ sfprintf(shp->strbuf, "<SIG%x-code%x>", signo, sicode);
+ break;
+ }
+
+ if (str)
+ {
+ /* FIXME: What's the |stkcopy()| equivalent for str buffers
again ? */
+ sfprintf(shp->strbuf, "%s", str);
+ }
+
+ return sfstruse(shp->strbuf);
+}
+
void sh_setsiginfo(siginfo_t *sip)
{
Namval_t *np;
@@ -2052,22 +2163,20 @@
sp = (struct Svars*)fp;
np = create_svar(SH_SIG,"signo",0, fp);
np->nvalue.ip = &sip->si_signo;
- np = create_svar(SH_SIG,"name",0, fp);
+ np = create_svar(SH_SIG,"signame",0, fp);
sh_siglist(sp->sh,sp->sh->strbuf,sip->si_signo+1);
nv_putval(np,sfstruse(sp->sh->strbuf),NV_RDONLY);
np = create_svar(SH_SIG,"pid",0, fp);
np->nvalue.idp = &sip->si_pid;
np = create_svar(SH_SIG,"uid",0, fp);
np->nvalue.idp = &sip->si_uid;
+
np = create_svar(SH_SIG,"code",0, fp);
- np->nvalue.ip = &sip->si_code;
+ nv_putval(np, siginfocode2name(sp->sh, sip->si_signo,
sip->si_code),NV_RDONLY);
+
np = create_svar(SH_SIG,"status",0, fp);
-#ifdef CLD_EXITED
- if(sip->si_code==CLD_EXITED)
- sip->si_status &= 0xf;
-#endif
np->nvalue.ip = &sip->si_status;
- np->nvalue.ip = &sip->si_code;
+
np = create_svar(SH_SIG,"addr",0, fp);
np->nvsize = 16;
np->nvalue.llp = (Sflong_t*)&sip->si_addr;
diff -r -u build_i386_64bit_debug_unpatched/src/cmd/ksh93/sh/jobs.c
build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/sh/jobs.c
--- build_i386_64bit_debug_unpatched/src/cmd/ksh93/sh/jobs.c 2013-02-22
17:10:52.000000000 +0100
+++ build_i386_64bit_debug_sigchld_shsig/src/cmd/ksh93/sh/jobs.c
2013-03-28 00:48:58.355797312 +0100
@@ -196,6 +196,7 @@
register struct process *pw,*pwnext;
pid_t bckpid;
int oldexit,trapnote;
+ siginfo_t si;
job_lock();
shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP;
trapnote = shp->trapnote;
@@ -212,6 +213,21 @@
shp->savexit = pw->p_exit;
if(pw->p_flag&P_SIGNALLED)
shp->savexit |= SH_EXITSIG;
+
+#ifdef _lib_sigaction
+ /*
+ * We craft our own siginfo_t data here. This
+ * should be replaced later with code which
+ * just saves the siginfo_t data in the signal
+ * handler and replays it for the matching trap
+ */
+ memset(&si, 0, sizeof(si));
+ si.si_signo=SIGCHLD;
+ si.si_pid=pw->p_pid;
+ si.si_code=CLD_EXITED;
+ si.si_status=pw->p_exit;
+ sh_setsiginfo(&si);
+#endif
sh_trap(shp,trap,0);
if(pw->p_pid==bckpid && unpost)
job_unpost(shp,pw,0);
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers