From 4b241872ef56389e6bcf4ab602cd52989cf3151d Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 26 Mar 2007 14:26:32 +0000 Subject: fix wait --- src/cmd/rc/fns.h | 4 + src/cmd/rc/havefork.c | 51 ++++++++++- src/cmd/rc/havep9p.c | 246 -------------------------------------------------- src/cmd/rc/mkfile | 2 +- src/cmd/rc/plan9ish.c | 45 ++++++++- 5 files changed, 97 insertions(+), 251 deletions(-) delete mode 100644 src/cmd/rc/havep9p.c (limited to 'src/cmd/rc') diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h index f6454787..c4d201dc 100644 --- a/src/cmd/rc/fns.h +++ b/src/cmd/rc/fns.h @@ -22,6 +22,7 @@ void Updenv(void); void Vinit(void); int Waitfor(int, int); long Write(int, char*, long); +void addwaitpid(int); int advance(void); int back(int); void cleanhere(char*); @@ -30,10 +31,12 @@ int compile(tree*); char * list2str(word*); int count(word*); void deglob(char*); +void delwaitpid(int); void dotrap(void); void freenodes(void); void freewords(word*); void globlist(void); +int havewaitpid(int); int idchr(int); void inttoascii(char*, long); void kinit(void); @@ -41,6 +44,7 @@ int mapfd(int); int match(char*, char*, int); int matchfn(char*, char*); char** mkargv(word*); +void clearwaitpids(void); void panic(char*, int); void pathinit(void); void poplist(void); diff --git a/src/cmd/rc/havefork.c b/src/cmd/rc/havefork.c index e81046d6..45419f0d 100644 --- a/src/cmd/rc/havefork.c +++ b/src/cmd/rc/havefork.c @@ -1,3 +1,9 @@ +#include +#include +#if defined(PLAN9PORT) && defined(__sun__) +# define BSD_COMP /* sigh. for TIOCNOTTY */ +#endif +#include #include "rc.h" #include "getflags.h" #include "exec.h" @@ -10,6 +16,7 @@ void Xasync(void) { int null = open("/dev/null", 0); + int tty; int pid; char npid[10]; if(null<0){ @@ -22,11 +29,39 @@ Xasync(void) Xerror("try again"); break; case 0: - pushredir(ROPEN, null, 0); + clearwaitpids(); + /* + * I don't know what the right thing to do here is, + * so this is all experimentally determined. + * If we just dup /dev/null onto 0, then running + * ssh foo & will reopen /dev/tty, try to read a password, + * get a signal, and repeat, in a tight loop, forever. + * Arguably this is a bug in ssh (it behaves the same + * way under bash as under rc) but I'm fixing it here + * anyway. If we dissociate the process from the tty, + * then it won't be able to open /dev/tty ever again. + * The SIG_IGN on SIGTTOU makes writing the tty + * (via fd 1 or 2, for example) succeed even though + * our pgrp is not the terminal's controlling pgrp. + */ + if((tty = open("/dev/tty", OREAD)) >= 0){ + /* + * Should make reads of tty fail, writes succeed. + */ + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + ioctl(tty, TIOCNOTTY); + close(tty); + } + if(isatty(0)) + pushredir(ROPEN, null, 0); + else + close(null); start(runq->code, runq->pc+1, runq->local); runq->ret = 0; break; default: + addwaitpid(pid); close(null); runq->pc = runq->code[runq->pc].i; inttoascii(npid, pid); @@ -52,12 +87,14 @@ Xpipe(void) Xerror("try again"); break; case 0: + clearwaitpids(); start(p->code, pc+2, runq->local); runq->ret = 0; close(pfd[PRD]); pushredir(ROPEN, pfd[PWR], lfd); break; default: + addwaitpid(forkid); start(p->code, p->code[pc].i, runq->local); close(pfd[PWR]); pushredir(ROPEN, pfd[PRD], rfd); @@ -93,11 +130,13 @@ Xbackq(void) close(pfd[PWR]); return; case 0: + clearwaitpids(); close(pfd[PRD]); start(runq->code, runq->pc+1, runq->local); pushredir(ROPEN, pfd[PWR], 1); return; default: + addwaitpid(pid); close(pfd[PWR]); f = openfd(pfd[PRD]); s = wd; @@ -134,7 +173,7 @@ void Xpipefd(void) { struct thread *p = runq; - int pc = p->pc; + int pc = p->pc, pid; char name[40]; int pfd[2]; int sidefd, mainfd; @@ -150,17 +189,19 @@ Xpipefd(void) sidefd = pfd[PRD]; mainfd = pfd[PWR]; } - switch(fork()){ + switch(pid = fork()){ case -1: Xerror("try again"); break; case 0: + clearwaitpids(); start(p->code, pc+2, runq->local); close(mainfd); pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); runq->ret = 0; break; default: + addwaitpid(pid); close(sidefd); pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ strcpy(name, Fdprefix); @@ -180,10 +221,12 @@ Xsubshell(void) Xerror("try again"); break; case 0: + clearwaitpids(); start(runq->code, runq->pc+1, runq->local); runq->ret = 0; break; default: + addwaitpid(pid); Waitfor(pid, 1); runq->pc = runq->code[runq->pc].i; break; @@ -201,6 +244,7 @@ execforkexec(void) case -1: return -1; case 0: + clearwaitpids(); pushword("exec"); execexec(); strcpy(buf, "can't exec: "); @@ -208,5 +252,6 @@ execforkexec(void) errstr(buf+n, ERRMAX-n); Exit(buf); } + addwaitpid(pid); return pid; } diff --git a/src/cmd/rc/havep9p.c b/src/cmd/rc/havep9p.c deleted file mode 100644 index 29e2272b..00000000 --- a/src/cmd/rc/havep9p.c +++ /dev/null @@ -1,246 +0,0 @@ -#include -#include -#if defined(PLAN9PORT) && defined(__sun__) -# define BSD_COMP /* sigh. for TIOCNOTTY */ -#endif -#include -#include "rc.h" -#include "getflags.h" -#include "exec.h" -#include "io.h" -#include "fns.h" - -int havefork = 1; - -void -Xasync(void) -{ - int null=open("/dev/null", 0); - int tty; - int pid; - char npid[10]; - if(null<0){ - Xerror("Can't open /dev/null\n"); - return; - } - switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){ - case -1: - close(null); - Xerror("try again"); - break; - case 0: - /* - * I don't know what the right thing to do here is, - * so this is all experimentally determined. - * If we just dup /dev/null onto 0, then running - * ssh foo & will reopen /dev/tty, try to read a password, - * get a signal, and repeat, in a tight loop, forever. - * Arguably this is a bug in ssh (it behaves the same - * way under bash as under rc) but I'm fixing it here - * anyway. If we dissociate the process from the tty, - * then it won't be able to open /dev/tty ever again. - * The SIG_IGN on SIGTTOU makes writing the tty - * (via fd 1 or 2, for example) succeed even though - * our pgrp is not the terminal's controlling pgrp. - */ - if((tty=open("/dev/tty", OREAD)) >= 0){ - /* - * Should make reads of tty fail, writes succeed. - */ - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - ioctl(tty, TIOCNOTTY); - close(tty); - } - if(isatty(0)) - pushredir(ROPEN, null, 0); - else - close(null); - start(runq->code, runq->pc+1, runq->local); - runq->ret=0; - break; - default: - close(null); - runq->pc=runq->code[runq->pc].i; - inttoascii(npid, pid); - setvar("apid", newword(npid, (word *)0)); - break; - } -} - -void -Xpipe(void) -{ - struct thread *p = runq; - int pc = p->pc, forkid; - int lfd = p->code[pc++].i; - int rfd = p->code[pc++].i; - int pfd[2]; - - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - switch(forkid=fork()){ - case -1: - Xerror("try again"); - break; - case 0: - start(p->code, pc+2, runq->local); - runq->ret=0; - close(pfd[PRD]); - pushredir(ROPEN, pfd[PWR], lfd); - break; - default: - start(p->code, p->code[pc].i, runq->local); - close(pfd[PWR]); - pushredir(ROPEN, pfd[PRD], rfd); - p->pc=p->code[pc+1].i; - p->pid=forkid; - break; - } -} - -void -Xbackq(void) -{ - char wd[8193]; - int c; - char *s, *ewd = &wd[8192], *stop; - struct io *f; - var *ifs = vlook("ifs"); - word *v, *nextv; - int pfd[2]; - int pid; - - stop = ifs->val?ifs->val->word:""; - if(pipe(pfd)<0){ - Xerror("can't make pipe"); - return; - } - switch(pid = fork()){ - case -1: Xerror("try again"); - close(pfd[PRD]); - close(pfd[PWR]); - return; - case 0: - close(pfd[PRD]); - start(runq->code, runq->pc+1, runq->local); - pushredir(ROPEN, pfd[PWR], 1); - return; - default: - close(pfd[PWR]); - f=openfd(pfd[PRD]); - s=wd; - v=0; - while((c=rchr(f))!=EOF){ - if(strchr(stop, c) || s==ewd){ - if(s!=wd){ - *s='\0'; - v=newword(wd, v); - s=wd; - } - } - else *s++=c; - } - if(s!=wd){ - *s='\0'; - v=newword(wd, v); - } - closeio(f); - Waitfor(pid, 0); - /* v points to reversed arglist -- reverse it onto argv */ - while(v){ - nextv=v->next; - v->next=runq->argv->words; - runq->argv->words=v; - v=nextv; - } - runq->pc=runq->code[runq->pc].i; - return; - } -} - -/* - * Who should wait for the exit from the fork? - */ -void -Xpipefd(void) -{ - struct thread *p=runq; - int pc=p->pc; - char name[40]; - int pfd[2]; - int sidefd, mainfd; - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - if(p->code[pc].i==READ){ - sidefd=pfd[PWR]; - mainfd=pfd[PRD]; - } - else{ - sidefd=pfd[PRD]; - mainfd=pfd[PWR]; - } - switch(fork()){ - case -1: - Xerror("try again"); - break; - case 0: - start(p->code, pc+2, runq->local); - close(mainfd); - pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); - runq->ret=0; - break; - default: - close(sidefd); - pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ - strcpy(name, Fdprefix); - inttoascii(name+strlen(name), mainfd); - pushword(name); - p->pc=p->code[pc+1].i; - break; - } -} - -void -Xsubshell(void) -{ - int pid; - switch(pid=fork()){ - case -1: - Xerror("try again"); - break; - case 0: - start(runq->code, runq->pc+1, runq->local); - runq->ret=0; - break; - default: - Waitfor(pid, 1); - runq->pc=runq->code[runq->pc].i; - break; - } -} - -int -execforkexec(void) -{ - int pid; - int n; - char buf[ERRMAX]; - - switch(pid = fork()){ - case -1: - return -1; - case 0: - pushword("exec"); - execexec(); - strcpy(buf, "can't exec: "); - n = strlen(buf); - errstr(buf+n, ERRMAX-n); - Exit(buf); - } - return pid; -} diff --git a/src/cmd/rc/mkfile b/src/cmd/rc/mkfile index d1144e85..79b407f8 100644 --- a/src/cmd/rc/mkfile +++ b/src/cmd/rc/mkfile @@ -20,7 +20,7 @@ OFILES=\ var.$O\ y.tab.$O\ plan9ish.$O\ - havep9p.$O\ + havefork.$O\ HFILES=\ rc.h\ diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c index 1e896536..da9d8679 100644 --- a/src/cmd/rc/plan9ish.c +++ b/src/cmd/rc/plan9ish.c @@ -199,7 +199,10 @@ int Waitfor(int pid, int unused0){ Waitmsg *w; char errbuf[ERRMAX]; + if(pid >= 0 && !havewaitpid(pid)) + return 0; while((w = wait()) != nil){ + delwaitpid(w->pid); if(w->pid==pid){ if(strncmp(w->msg, "signal: ", 8) == 0) fprint(mapfd(2), "%d: %s\n", w->pid, w->msg); @@ -217,7 +220,7 @@ int Waitfor(int pid, int unused0){ free(w); } - errstr(errbuf, sizeof errbuf); + rerrstr(errbuf, sizeof errbuf); if(strcmp(errbuf, "interrupted")==0) return -1; return 0; } @@ -559,3 +562,43 @@ exitcode(char *msg) n = 1; return n; } + +int *waitpids; +int nwaitpids; + +void +addwaitpid(int pid) +{ + waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); + if(waitpids == 0) + panic("Can't realloc %d waitpids", nwaitpids+1); + waitpids[nwaitpids++] = pid; +} + +void +delwaitpid(int pid) +{ + int r, w; + + for(r=w=0; r