#include <errno.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#define NODEFINE
#include <u.h>
#include <libc.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1