ref: 5ac6c1f2faef87d74d686546615332320ede3f14
parent: 7539ef43361f1579bd03b0b4007465adb8872aa0
author: glenda <glenda@cirno>
date: Sun Mar 23 07:08:56 EDT 2025
more defensive coding for history
--- a/wind.c
+++ b/wind.c
@@ -1411,11 +1411,13 @@
Rectangle r;
w = emalloc(sizeof(Window));
- w->history = emalloc(w->maxhistory * sizeof(Rune*));
- w->historylens = emalloc(w->maxhistory * sizeof(int));
w->nhistory = 0;
w->maxhistory = 100;
w->histpos = -1;
+ w->history = emalloc(w->maxhistory * sizeof(Rune*));
+ w->historylens = emalloc(w->maxhistory * sizeof(int));
+ for(int i = 0; i < w->maxhistory; i++)
+ w->history[i] = nil;
w->savedcmd = nil;
w->nsavedcmd = 0;
w->screenr = i->r;
@@ -1497,32 +1499,55 @@
wclose(Window *w)
{
int i;
-
+ static void *already_closing = nil;
+
+ /* Prevent recursion */
+ if(w == already_closing)
+ return 0;
+
i = decref(w);
if(i > 0)
return 0;
- if(i < 0)
- error("negative ref count");
+ if(i < 0) {
+ fprint(2, "rio: negative ref count in wclose\n");
+ i = 0;
+ }
- /* we might get receieve multiple close requests */
- if(w->history) {
- for(i = 0; i < w->nhistory; i++)
- free(w->history[i]);
+ already_closing = w;
+
+ if(w->history != nil) {
+ if(w->nhistory > 0 && w->nhistory <= w->maxhistory) {
+ for(i = 0; i < w->nhistory; i++) {
+ if(w->history[i] != nil) {
+ free(w->history[i]);
+ w->history[i] = nil;
+ }
+ }
+ }
free(w->history);
- free(w->historylens);
w->history = nil;
- w->historylens = nil;
+
+ if(w->historylens != nil) {
+ free(w->historylens);
+ w->historylens = nil;
+ }
w->nhistory = 0;
+ w->maxhistory = 0;
}
- if(w->savedcmd) {
+ if(w->savedcmd != nil) {
free(w->savedcmd);
w->savedcmd = nil;
w->nsavedcmd = 0;
}
+ w->histpos = -1;
+
wclunk(w);
wsendctlmesg(w, Exited, ZR, nil);
+
+ already_closing = nil;
+
return 1;
}
@@ -1541,6 +1566,16 @@
wctlmesg(Window *w, int m, Rectangle r, void *p)
{
Image *i = p;
+ Channel *mc = w->mc.c;
+ Channel *ck = w->ck;
+ Channel *cctl = w->cctl;
+ Channel *conswrite = w->conswrite;
+ Channel *consread = w->consread;
+ Channel *mouseread = w->mouseread;
+ Channel *wctlread = w->wctlread;
+ Channel *kbdread = w->kbdread;
+ Channel *complete = w->complete;
+ Channel *gone = w->gone;
switch(m){
default:
@@ -1623,21 +1658,25 @@
flushimage(display, 1);
break;
case Exited:
+
+
wclosewin(w);
frclear(w, TRUE);
flushimage(display, 1);
if(w->notefd >= 0)
close(w->notefd);
- chanfree(w->mc.c);
- chanfree(w->ck);
- chanfree(w->cctl);
- chanfree(w->conswrite);
- chanfree(w->consread);
- chanfree(w->mouseread);
- chanfree(w->wctlread);
- chanfree(w->kbdread);
- chanfree(w->complete);
- chanfree(w->gone);
+
+ chanfree(mc);
+ chanfree(ck);
+ chanfree(cctl);
+ chanfree(conswrite);
+ chanfree(consread);
+ chanfree(mouseread);
+ chanfree(wctlread);
+ chanfree(kbdread);
+ chanfree(complete);
+ chanfree(gone);
+
free(w->raw);
free(w->r);
free(w->dir);
@@ -1847,10 +1886,12 @@
if(wctlmesg(w, wcm.type, wcm.r, wcm.p) == Exited){
while(kbdqr != kbdqw)
free(kbdq[kbdqr++ % nelem(kbdq)]);
+
chanfree(crm.c1);
chanfree(crm.c2);
chanfree(mrm.cm);
chanfree(cwm.cw);
+
threadexits(nil);
}
continue;