#include #include #include #include #include #include #include #define NODEFINE #include #include #include "sig.h" typedef struct Waitevent Waitevent; struct Waitevent { Waitevent *next; char msg[256]; int iserror; }; static ILock waitilock; static QLock dataready; static Waitevent *head, *tail; int pm_await(char *s, int n) { char *e; Waitevent *w; while(!pm_canqlock(&dataready)) if(pm_checkkids() < 0) return -1; pm_ilock(&waitilock); w = head; pm_assert(w != nil); head = w->next; if(head == nil) tail = nil; else pm_qunlock(&dataready); pm_iunlock(&waitilock); if(pm_debug & PmDebugWait) pm_fprint(2, "w %p: %s%s (head=%p)\n", w, w->iserror?" (err)":"", w->msg, head); if(w->iserror){ pm_werrstr("%s", w->msg); pm_free(w); return -1; }else{ e = pm_utfecpy(s, s+n, w->msg); pm_free(w); return e-s; } } void pm_waitinit(void) { pm_qlock(&dataready); } int pm_checkkids(void) { pid_t pidt; ulong usertime, systemtime, realtime, pid; int status; char stbuf[128]; struct rusage rusage; Waitevent *w; while((pidt = wait4(-1, &status, WNOHANG, &rusage)) != 0){ if(pidt < 0){ /* no kids */ pm_oserror(); return -1; } if(WIFSTOPPED(status)){ if(pm_debug & PmDebugWait) pm_fprint(2, "pid %d: wait4: process stopped\n", getpid()); continue; } pid = pidt; usertime = rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000; systemtime = rusage.ru_stime.tv_sec*1000 + rusage.ru_stime.tv_usec/1000; realtime = 0; strcpy(stbuf, "cannot happen in pm_await"); if(WIFEXITED(status)){ if(WEXITSTATUS(status) == 0) stbuf[0] = '\0'; else pm_snprint(stbuf, sizeof stbuf, "%d", status); } if(WIFSIGNALED(status)){ if(0 <= WTERMSIG(status) && WTERMSIG(status) < pm_nsigtab) pm_strcpy(stbuf, pm_sigtab[WTERMSIG(status)].desc); else pm_snprint(stbuf, sizeof stbuf, "signal %d", WTERMSIG(status)); if(WCOREDUMP(status)) pm_strcat(stbuf, " (core dumped)"); } pm_quotefmtinstall(); w = pm_malloc(sizeof(*w)); w->iserror = 0; pm_snprint(w->msg, sizeof w->msg, "%lud %lud %lud %lud %q", pid, usertime, systemtime, realtime, stbuf); w->next = nil; if(pm_debug & PmDebugWait) pm_fprint(2, "pid %d: checkkids %p: %s\n", getpid(), w, w->msg); pm_ilock(&waitilock); if(tail){ tail->next = w; tail = w; }else{ head = tail = w; pm_qunlock(&dataready); } pm_iunlock(&waitilock); } return 0; }