tfix edit pipe bug - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 663017560218b62119022f9f4360cf6eb05a36e2
 (DIR) parent 11b0772a33026b44fd0a7f8a8d757d2f6a218878
 (HTM) Author: rsc <devnull@localhost>
       Date:   Fri,  5 May 2006 04:55:14 +0000
       
       fix edit pipe bug
       
       Diffstat:
         M src/cmd/acme/dat.h                  |       3 +++
         M src/cmd/acme/ecmd.c                 |      18 ++++++++++++++++++
         M src/cmd/acme/xfid.c                 |      29 +++++++++++++++++++++++++++--
       
       3 files changed, 48 insertions(+), 2 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h
       t@@ -269,6 +269,7 @@ struct Window
                int                tagexpand;
                int                taglines;
                Rectangle        tagtop;
       +        QLock        editoutlk;
        };
        
        void        wininit(Window*, Window*, Rectangle);
       t@@ -562,4 +563,6 @@ Channel        *cerr;                /* chan(char*) */
        Channel        *cedit;                /* chan(int) */
        Channel        *cwarn;                /* chan(void*)[1] (really chan(unit)[1]) */
        
       +QLock        editoutlk;
       +
        #define        STACK        32768
 (DIR) diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c
       t@@ -592,6 +592,7 @@ runpipe(Text *t, int cmd, Rune *cr, int ncr, int state)
                int n;
                Runestr dir;
                Window *w;
       +        QLock *q;
        
                r = skipbl(cr, ncr, &n);
                if(n == 0)
       t@@ -626,6 +627,23 @@ runpipe(Text *t, int cmd, Rune *cr, int ncr, int state)
                        winunlock(t->w);
                qunlock(&row.lk);
                recvul(cedit);
       +        /*
       +         * The editoutlk exists only so that we can tell when
       +         * the editout file has been closed.  It can get closed *after*
       +         * the process exits because, since the process cannot be 
       +         * connected directly to editout (no 9P kernel support), 
       +         * the process is actually connected to a pipe to another
       +         * process (arranged via 9pserve) that reads from the pipe
       +         * and then writes the data in the pipe to editout using
       +         * 9P transactions.  This process might still have a couple
       +         * writes left to copy after the original process has exited.
       +         */
       +        if(w)
       +                q = &w->editoutlk;
       +        else
       +                q = &editoutlk;
       +        qlock(q);        /* wait for file to close */
       +        qunlock(q);
                qlock(&row.lk);
                editing = Inactive;
                if(t!=nil && t->w!=nil)
 (DIR) diff --git a/src/cmd/acme/xfid.c b/src/cmd/acme/xfid.c
       t@@ -98,9 +98,9 @@ xfidopen(Xfid *x)
        
                w = x->f->w;
                t = &w->body;
       +        q = FILE(x->f->qid);
                if(w){
                        winlock(w, 'E');
       -                q = FILE(x->f->qid);
                        switch(q){
                        case QWaddr:
                                if(w->nopen[q]++ == 0){
       t@@ -174,11 +174,26 @@ xfidopen(Xfid *x)
                                        respond(x, &fc, Eperm);
                                        return;
                                }
       +                        if(!canqlock(&w->editoutlk)){
       +                                winunlock(w);
       +                                respond(x, &fc, Einuse);
       +                                return;
       +                        }
                                w->wrselrange = range(t->q1, t->q1);
                                break;
                        }
                        winunlock(w);
                }
       +        else{
       +                switch(q){
       +                case Qeditout:
       +                        if(!canqlock(&editoutlk)){
       +                                respond(x, &fc, Einuse);
       +                                return;
       +                        }
       +                        break;
       +                }
       +        }
                fc.qid = x->f->qid;
                fc.iounit = messagesize-IOHDRSZ;
                x->f->open = TRUE;
       t@@ -203,10 +218,10 @@ xfidclose(Xfid *x)
                        return;
                }
        
       +        q = FILE(x->f->qid);
                x->f->open = FALSE;
                if(w){
                        winlock(w, 'E');
       -                q = FILE(x->f->qid);
                        switch(q){
                        case QWctl:
                                if(w->ctlfid!=~0 && w->ctlfid==x->f->fid){
       t@@ -247,10 +262,20 @@ xfidclose(Xfid *x)
                                        min(w->wrselrange.q1, t->file->b.nc), 1);
                                textscrdraw(t);
                                break;
       +                case QWeditout:
       +                        qunlock(&w->editoutlk);
       +                        break;
                        }
                        winunlock(w);
                        winclose(w);
                }
       +        else{
       +                switch(q){
       +                case Qeditout:
       +                        qunlock(&editoutlk);
       +                        break;
       +                }
       +        }
                respond(x, &fc, nil);
        }