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);
--
⑨