URI: 
       tfix wait - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 4b241872ef56389e6bcf4ab602cd52989cf3151d
   DIR parent bd1b0cc17e58f8135fa0888cdb2d4fac61f85bce
  HTML Author: rsc <devnull@localhost>
       Date:   Mon, 26 Mar 2007 14:26:32 +0000
       
       fix wait
       
       Diffstat:
         M src/cmd/rc/fns.h                    |       4 ++++
         M src/cmd/rc/havefork.c               |      51 +++++++++++++++++++++++++++++--
         D src/cmd/rc/havep9p.c                |     246 -------------------------------
         M src/cmd/rc/mkfile                   |       2 +-
         M src/cmd/rc/plan9ish.c               |      45 ++++++++++++++++++++++++++++++-
       
       5 files changed, 97 insertions(+), 251 deletions(-)
       ---
   DIR diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h
       t@@ -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*);
       t@@ -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);
       t@@ -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);
   DIR diff --git a/src/cmd/rc/havefork.c b/src/cmd/rc/havefork.c
       t@@ -1,3 +1,9 @@
       +#include <u.h>
       +#include <signal.h>
       +#if defined(PLAN9PORT) && defined(__sun__)
       +#        define BSD_COMP        /* sigh.  for TIOCNOTTY */
       +#endif
       +#include <sys/ioctl.h>
        #include "rc.h"
        #include "getflags.h"
        #include "exec.h"
       t@@ -10,6 +16,7 @@ void
        Xasync(void)
        {
                int null = open("/dev/null", 0);
       +        int tty;
                int pid;
                char npid[10];
                if(null<0){
       t@@ -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);
       t@@ -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);
       t@@ -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;
       t@@ -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;
       t@@ -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);
       t@@ -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;
       t@@ -201,6 +244,7 @@ execforkexec(void)
                case -1:
                        return -1;
                case 0:
       +                clearwaitpids();
                        pushword("exec");
                        execexec();
                        strcpy(buf, "can't exec: ");
       t@@ -208,5 +252,6 @@ execforkexec(void)
                        errstr(buf+n, ERRMAX-n);
                        Exit(buf);
                }
       +        addwaitpid(pid);
                return pid;
        }
   DIR diff --git a/src/cmd/rc/havep9p.c b/src/cmd/rc/havep9p.c
       t@@ -1,246 +0,0 @@
       -#include <u.h>
       -#include <signal.h>
       -#if defined(PLAN9PORT) && defined(__sun__)
       -#        define BSD_COMP        /* sigh.  for TIOCNOTTY */
       -#endif
       -#include <sys/ioctl.h>
       -#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;
       -}
   DIR diff --git a/src/cmd/rc/mkfile b/src/cmd/rc/mkfile
       t@@ -20,7 +20,7 @@ OFILES=\
                var.$O\
                y.tab.$O\
                plan9ish.$O\
       -        havep9p.$O\
       +        havefork.$O\
        
        HFILES=\
                rc.h\
   DIR diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c
       t@@ -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);
       t@@ -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;
        }
       t@@ -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<nwaitpids; r++)
       +                if(waitpids[r] != pid)
       +                        waitpids[w++] = waitpids[r];
       +        nwaitpids = w;
       +}
       +
       +void
       +clearwaitpids(void)
       +{
       +        nwaitpids = 0;
       +}
       +
       +int
       +havewaitpid(int pid)
       +{
       +        int i;
       +        
       +        for(i=0; i<nwaitpids; i++)
       +                if(waitpids[i] == pid)
       +                        return 1;
       +        return 0;
       +}