ref: e2bfa1a57cd5b9b771fb8a33f6b4bc54165d4be8
parent: a664cf0bb19c82286560bb5114192d524b63d9f4
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);
--
⑨