Commit Diff


commit - 201e19d672a2dab81e213237569022607aced2e1
commit + 880ab2f10a2d4922d314ff8d016ea078f3c7f019
blob - 4d8d3cdf49b1c9f79ceceb889fc35fd87b09e4cf
blob + 87d4e7b0f45338983d8c2274ecac9d1f5735ca93
--- src/cmd/acme/mail/dat.h
+++ src/cmd/acme/mail/dat.h
@@ -25,6 +25,10 @@ struct Event
 
 struct Window
 {
+	/* coordinate wineventproc and window thread */
+	QLock	lk;
+	int		ref;
+
 	/* file descriptors */
 	CFid*		ctl;
 	CFid*		event;
@@ -112,6 +116,8 @@ extern	int		winsetaddr(Window*, char*, int);
 extern	char*	winreadbody(Window*, int*);
 extern	void		windormant(Window*);
 extern	void		winsetdump(Window*, char*, char*);
+extern	void		winincref(Window*);
+extern	void		windecref(Window*);
 
 extern	void		readmbox(Message*, char*, char*);
 extern	void		rewritembox(Window*, Message*);
blob - ac74b63423f446d9183c40950dc99905d7e16871
blob + f8030ca4f8251f08744ad7fb424c864614c6c234
--- src/cmd/acme/mail/mail.c
+++ src/cmd/acme/mail/mail.c
@@ -470,6 +470,7 @@ mainctl(void *v)
 	char *s, *t, *buf;
 
 	w = v;
+	winincref(w);
 	proccreate(wineventproc, w, STACK);
 
 	for(;;){
blob - 9c4e0bb4aab4cd928d303657682d967a38fdbbfc
blob + 9406b7993d5a43f3ed09c6c7d07f6cba49bd6da6
--- src/cmd/acme/mail/mesg.c
+++ src/cmd/acme/mail/mesg.c
@@ -720,8 +720,7 @@ mesgcommand(Message *m, char *cmd)
 	}
 	if(strcmp(args[0], "Del") == 0){
 		if(windel(m->w, 0)){
-			chanfree(m->w->cevent);
-			free(m->w);
+			windecref(m->w);
 			m->w = nil;
 			if(m->isreply)
 				delreply(m);
@@ -886,6 +885,7 @@ mesgctl(void *v)
 	m = v;
 	w = m->w;
 	threadsetname("mesgctl");
+	winincref(w);
 	proccreate(wineventproc, w, STACK);
 	for(;;){
 		e = recvp(w->cevent);
blob - e407b0c3ade40e29b87c021b32773bc79fd2e9c4
blob + 8a3e60a90eacc7c8361ad830dc377cf9cc7473a5
--- src/cmd/acme/mail/win.c
+++ src/cmd/acme/mail/win.c
@@ -24,10 +24,32 @@ newwindow(void)
 	w->body = nil;
 	w->data = nil;
 	w->cevent = chancreate(sizeof(Event*), 0);
+	w->ref = 1;
 	return w;
 }
 
 void
+winincref(Window *w)
+{
+	qlock(&w->lk);
+	++w->ref;
+	qunlock(&w->lk);
+}
+
+void
+windecref(Window *w)
+{
+	qlock(&w->lk);
+	if(--w->ref > 0){
+		qunlock(&w->lk);
+		return;
+	}
+	fsclose(w->event);
+	chanfree(w->cevent);
+	free(w);
+}
+
+void
 winsetdump(Window *w, char *dir, char *cmd)
 {
 	if(dir != nil)
@@ -125,6 +147,7 @@ wingetec(Window *w)
 		w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
 		if(w->nbuf <= 0){
 			/* probably because window has exited, and only called by wineventproc, so just shut down */
+			windecref(w);
 			threadexits(nil);
 		}
 		w->bufp = w->buf;
@@ -255,8 +278,6 @@ windel(Window *w, int sure)
 	windormant(w);
 	fsclose(w->ctl);
 	w->ctl = nil;
-	fsclose(w->event);
-	w->event = nil;
 	return 1;
 }