git: 9front

Download patch

ref: 2fd74261ec1bab9ac2524115bbd4a4c96d310e77
parent: c968cf88a96c8b0dadd36750a0626d6bbbec455e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Jun 18 17:04:17 EDT 2025

kernel: attach text segment outside of up->seglock in sysexec()

The attachimage() call can be expensive as it might
need to reclaim some old images from the cache.

So do the attachimage() when up->seglock is released
(before the point of no return).

This means attachimage() can now trigger the pager
and any failures here just yield exec returning
with an error in the original process.

--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -295,7 +295,7 @@
 	int i, n, indir;
 	ulong magic, ssize, nargs, nbytes;
 	uintptr t, d, b, entry, text, data, bss, bssend, tstk, align;
-	Segment *s;
+	Segment *s, *ts;
 	Image *img;
 	Tos *tos;
 	Chan *tc;
@@ -520,6 +520,28 @@
 		n = i+1;
 	}
 
+	/* Attach text segment */
+	/* attachimage returns a locked cache image */
+	img = attachimage(tc);
+	if((ts = img->s) != nil && ts->flen == text){
+		assert(ts->image == img);
+		incref(ts);
+		putimage(img);
+	} else {
+		if(waserror()){
+			putimage(img);
+			nexterror();
+		}
+		ts = newseg(SG_TEXT | SG_RONLY, UTZERO, (t-UTZERO)>>PGSHIFT);
+		ts->flushme = 1;
+		ts->image = img;
+		ts->fstart = 0;
+		ts->flen = text;
+		img->s = ts;
+		unlock(img);
+		poperror();
+	}
+
 	/*
 	 * Committed.
 	 * Free old memory.
@@ -544,28 +566,8 @@
 		}
 	}
 
-	/* Text.  Shared. Attaches to cache image if possible */
-	/* attachimage returns a locked cache image */
-	img = attachimage(tc);
-	if((s = img->s) != nil && s->flen == text){
-		assert(s->image == img);
-		incref(s);
-		putimage(img);
-	} else {
-		if(waserror()){
-			putimage(img);
-			nexterror();
-		}
-		s = newseg(SG_TEXT | SG_RONLY, UTZERO, (t-UTZERO)>>PGSHIFT);
-		s->flushme = 1;
-		s->image = img;
-		s->fstart = 0;
-		s->flen = text;
-		img->s = s;
-		unlock(img);
-		poperror();
-	}
-	up->seg[TSEG] = s;
+	/* Text. Shared. */
+	up->seg[TSEG] = ts;
 
 	/* Data. Shared. */
 	s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
@@ -584,8 +586,6 @@
 	 * Move the stack
 	 */
 	s = up->seg[ESEG];
-	if(s == nil)
-		error(Egreg);
 	up->seg[ESEG] = nil;
 	qlock(s);
 	s->base = USTKTOP-USTKSIZE;
@@ -596,15 +596,6 @@
 	qunlock(&up->seglock);
 	poperror();	/* seglock */
 
-	/*
-	 * Close on exec
-	 */
-	if((f = up->fgrp) != nil) {
-		for(i=0; i<=f->maxfd; i++)
-			fdclose(i, CCEXEC);
-	}
-
-	poperror();	/* tc */
 	if(tc == img->c){
 		/* avoid double caching */
 		tc->flag &= ~CCACHE;
@@ -611,8 +602,18 @@
 		cclunk(tc);
 	}
 	cclose(tc);
-	poperror();	/* file0 */
+	poperror();	/* tc */
+
 	free(file0);
+	poperror();	/* file0 */
+
+	/*
+	 * Close on exec
+	 */
+	if((f = up->fgrp) != nil) {
+		for(i=0; i<=f->maxfd; i++)
+			fdclose(i, CCEXEC);
+	}
 
 	qlock(&up->debug);
 	free(up->text);
--