From 663017560218b62119022f9f4360cf6eb05a36e2 Mon Sep 17 00:00:00 2001 From: rsc Date: Fri, 5 May 2006 04:55:14 +0000 Subject: fix edit pipe bug --- src/cmd/acme/dat.h | 3 +++ src/cmd/acme/ecmd.c | 18 ++++++++++++++++++ src/cmd/acme/xfid.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h index 0bf82381..075ffe22 100644 --- a/src/cmd/acme/dat.h +++ b/src/cmd/acme/dat.h @@ -269,6 +269,7 @@ struct Window int tagexpand; int taglines; Rectangle tagtop; + QLock editoutlk; }; void wininit(Window*, Window*, Rectangle); @@ -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 diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c index ac578235..a507b50f 100644 --- a/src/cmd/acme/ecmd.c +++ b/src/cmd/acme/ecmd.c @@ -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) @@ -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) diff --git a/src/cmd/acme/xfid.c b/src/cmd/acme/xfid.c index 15b411ce..65ae2d99 100644 --- a/src/cmd/acme/xfid.c +++ b/src/cmd/acme/xfid.c @@ -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){ @@ -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; @@ -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){ @@ -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); } -- cgit v1.2.3