ref: 085bc82e05255be82f47000b850235afaae64d9e
parent: 7e1d4d0c4c7c4942bd3e399903c42a2344ad1687
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 6 08:41:34 EDT 2025
kernel: avoid smalloc() for process groups Make new*grp() / dup*grp() functions error() instead of waiting for memory to become available. This means rfork() will now return error when the system is out of memory instead of hanging and waiting until resources become available.
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -609,7 +609,9 @@
{
Mhead *mh;
- mh = smalloc(sizeof(Mhead));
+ mh = malloc(sizeof(Mhead));
+ if(mh == nil)
+ error(Enomem);
mh->ref = 1;
mh->from = from;
incref(from);
@@ -714,6 +716,11 @@
pg = up->pgrp;
wlock(&pg->ns);
+ if(waserror()){
+ wunlock(&pg->ns);
+ mountfree(nm);
+ nexterror();
+ }
l = &MOUNTH(pg, old->qid);
for(m = *l; m != nil; m = m->hash){
if(eqchan(m->from, old, 1))
@@ -730,8 +737,14 @@
* if this is a union mount, add the old
* node to the mount chain.
*/
- if(order != MREPL)
+ if(order != MREPL){
+ if(waserror()){
+ putmhead(m);
+ nexterror();
+ }
m->mount = newmount(old, 0, nil);
+ poperror();
+ }
*l = m;
}
wlock(&m->lock);
@@ -752,6 +765,7 @@
}
wunlock(&m->lock);
wunlock(&pg->ns);
+ poperror();
mountfree(um);
--- a/sys/src/9/port/devenv.c
+++ b/sys/src/9/port/devenv.c
@@ -395,6 +395,18 @@
devwstat,
};
+Egrp*
+newegrp(void)
+{
+ Egrp *eg;
+
+ eg = malloc(sizeof(Egrp));
+ if(eg == nil)
+ error(Enomem);
+ eg->ref = 1;
+ return eg;
+}
+
void
envcpy(Egrp *to, Egrp *from)
{
--- a/sys/src/9/port/pgrp.c
+++ b/sys/src/9/port/pgrp.c
@@ -27,7 +27,9 @@
{
Pgrp *p;
- p = smalloc(sizeof(Pgrp));
+ p = malloc(sizeof(Pgrp));
+ if(p == nil)
+ error(Enomem);
p->ref = 1;
return p;
}
@@ -37,7 +39,9 @@
{
Rgrp *r;
- r = smalloc(sizeof(Rgrp));
+ r = malloc(sizeof(Rgrp));
+ if(r == nil)
+ error(Enomem);
r->ref = 1;
return r;
}
@@ -102,17 +106,28 @@
wlock(&to->ns);
rlock(&from->ns);
+ if(waserror()){
+ runlock(&from->ns);
+ wunlock(&to->ns);
+ nexterror();
+ }
order = nil;
for(i = 0; i < MNTHASH; i++) {
l = &to->mnthash[i];
for(f = from->mnthash[i]; f != nil; f = f->hash) {
rlock(&f->lock);
+ if(waserror()){
+ runlock(&f->lock);
+ nexterror();
+ }
mh = newmhead(f->from);
*l = mh;
l = &mh->hash;
link = &mh->mount;
for(m = f->mount; m != nil; m = m->next) {
- n = smalloc(sizeof(Mount));
+ n = malloc(sizeof(Mount));
+ if(n == nil)
+ error(Enomem);
n->mountid = m->mountid;
n->mflag = m->mflag;
n->to = m->to;
@@ -124,6 +139,7 @@
link = &n->next;
}
runlock(&f->lock);
+ poperror();
}
}
/*
@@ -133,6 +149,7 @@
m->mountid = nextmount();
runlock(&from->ns);
wunlock(&to->ns);
+ poperror();
}
Fgrp*
@@ -142,12 +159,20 @@
Chan *c;
int i;
- new = smalloc(sizeof(Fgrp));
+ new = malloc(sizeof(Fgrp));
+ if(new == nil)
+ error(Enomem);
+ new->ref = 1;
if(f == nil){
- new->flag = smalloc(DELTAFD*sizeof(new->flag[0]));
- new->fd = smalloc(DELTAFD*sizeof(new->fd[0]));
new->nfd = DELTAFD;
- new->ref = 1;
+ new->fd = malloc(DELTAFD*sizeof(new->fd[0]));
+ new->flag = malloc(DELTAFD*sizeof(new->flag[0]));
+ if(new->fd == nil || new->flag == nil){
+ free(new->flag);
+ free(new->fd);
+ free(new);
+ error(Enomem);
+ }
return new;
}
@@ -158,26 +183,20 @@
if(i != 0)
new->nfd += DELTAFD - i;
new->fd = malloc(new->nfd*sizeof(new->fd[0]));
- if(new->fd == nil){
- unlock(f);
- free(new);
- error("no memory for fgrp");
- }
new->flag = malloc(new->nfd*sizeof(new->flag[0]));
- if(new->flag == nil){
+ if(new->fd == nil || new->flag == nil){
unlock(f);
+ free(new->flag);
free(new->fd);
free(new);
- error("no memory for fgrp");
+ error(Enomem);
}
- new->ref = 1;
-
new->maxfd = f->maxfd;
for(i = 0; i <= f->maxfd; i++) {
if((c = f->fd[i]) != nil){
- incref(c);
new->fd[i] = c;
new->flag[i] = f->flag[i];
+ incref(c);
}
}
unlock(f);
@@ -206,8 +225,8 @@
}
up->closingfgrp = nil;
- free(f->fd);
free(f->flag);
+ free(f->fd);
free(f);
}
@@ -247,7 +266,9 @@
{
Mount *m;
- m = smalloc(sizeof(Mount));
+ m = malloc(sizeof(Mount));
+ if(m == nil)
+ error(Enomem);
m->to = to;
incref(to);
m->mountid = nextmount();
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -214,6 +214,7 @@
_Noreturn void namelenerror(char*, int, char*);
int needpages(void*);
Chan* newchan(void);
+Egrp* newegrp(void);
int newfd(Chan*, int);
Mhead* newmhead(Chan*);
Mount* newmount(Chan*, int, char*);
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -45,14 +45,13 @@
oldfd = f->fd;
oldflag = f->flag;
newfd = malloc((nfd+DELTAFD)*sizeof(newfd[0]));
- if(newfd == nil)
- goto Exhausted;
- memmove(newfd, oldfd, nfd*sizeof(newfd[0]));
newflag = malloc((nfd+DELTAFD)*sizeof(newflag[0]));
- if(newflag == nil){
+ if(newfd == nil || newflag == nil){
+ free(newflag);
free(newfd);
goto Exhausted;
}
+ memmove(newfd, oldfd, nfd*sizeof(newfd[0]));
memmove(newflag, oldflag, nfd*sizeof(newflag[0]));
f->fd = newfd;
f->flag = newflag;
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -26,14 +26,15 @@
uintptr
sysrfork(va_list list)
{
- Proc *p;
- int n, i;
- Fgrp *ofg;
- Pgrp *opg;
- Rgrp *org;
- Egrp *oeg;
+ /*
+ * Code using RFNOMNT expects to block all but
+ * the following devices.
+ */
+ static char nomntdevs[] = "|decp";
+
ulong pid, flag;
- char *devs;
+ int n, i;
+ Proc *p;
flag = va_arg(list, ulong);
/* Check flags before we commit */
@@ -44,46 +45,82 @@
if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
error(Ebadarg);
- /*
- * Code using RFNOMNT expects to block all but
- * the following devices.
- */
- devs = "|decp";
if((flag&RFPROC) == 0) {
+ Fgrp *ofg;
+ Pgrp *opg;
+ Rgrp *org;
+ Egrp *oeg;
+
if(flag & (RFMEM|RFNOWAIT))
error(Ebadarg);
+
+ ofg = up->fgrp;
+ opg = up->pgrp;
+ org = up->rgrp;
+ oeg = up->egrp;
+
+ if(waserror()){
+ if(up->fgrp != ofg){
+ closefgrp(up->fgrp);
+ up->fgrp = ofg;
+ }
+ if(up->pgrp != opg){
+ closepgrp(up->pgrp);
+ up->pgrp = opg;
+ }
+ if(up->rgrp != org){
+ closergrp(up->rgrp);
+ up->rgrp = org;
+ }
+ if(up->egrp != oeg){
+ closeegrp(up->egrp);
+ up->egrp = oeg;
+ }
+ nexterror();
+ }
+
+ /* File descriptors */
if(flag & (RFFDG|RFCFDG)) {
- ofg = up->fgrp;
if(flag & RFFDG)
up->fgrp = dupfgrp(ofg);
else
up->fgrp = dupfgrp(nil);
- closefgrp(ofg);
}
+
+ /* Process group */
if(flag & (RFNAMEG|RFCNAMEG)) {
- opg = up->pgrp;
up->pgrp = newpgrp();
if(flag & RFNAMEG)
pgrpcpy(up->pgrp, opg);
/* inherit notallowed */
memmove(up->pgrp->notallowed, opg->notallowed, sizeof up->pgrp->notallowed);
- closepgrp(opg);
}
- if(flag & RFNOMNT)
- devmask(up->pgrp, 1, devs);
- if(flag & RFREND) {
- org = up->rgrp;
+
+ /* Rendezvous group */
+ if(flag & RFREND)
up->rgrp = newrgrp();
- closergrp(org);
- }
+
+ /* Environment group */
if(flag & (RFENVG|RFCENVG)) {
- oeg = up->egrp;
- up->egrp = smalloc(sizeof(Egrp));
- up->egrp->ref = 1;
+ up->egrp = newegrp();
if(flag & RFENVG)
envcpy(up->egrp, oeg);
- closeegrp(oeg);
}
+
+ if(ofg != up->fgrp)
+ closefgrp(ofg);
+ if(opg != up->pgrp)
+ closepgrp(opg);
+ if(org != up->rgrp)
+ closergrp(org);
+ if(oeg != up->egrp)
+ closeegrp(oeg);
+
+ poperror();
+
+ if(flag & RFNOMNT)
+ devmask(up->pgrp, 1, nomntdevs);
+
if(flag & RFNOTEG){
qlock(&up->debug);
setnoteid(up, 0); /* can't error() with 0 argument */
@@ -174,7 +211,7 @@
}
else {
p->fgrp = up->fgrp;
- incref(p->fgrp);
+ incref(up->fgrp);
}
/* Process groups */
@@ -187,33 +224,34 @@
}
else {
p->pgrp = up->pgrp;
- incref(p->pgrp);
+ incref(up->pgrp);
}
- if(flag & RFNOMNT)
- devmask(p->pgrp, 1, devs);
+ /* Rendezvous group */
if(flag & RFREND)
p->rgrp = newrgrp();
else {
- incref(up->rgrp);
p->rgrp = up->rgrp;
+ incref(up->rgrp);
}
/* Environment group */
if(flag & (RFENVG|RFCENVG)) {
- p->egrp = smalloc(sizeof(Egrp));
- p->egrp->ref = 1;
+ p->egrp = newegrp();
if(flag & RFENVG)
envcpy(p->egrp, up->egrp);
}
else {
p->egrp = up->egrp;
- incref(p->egrp);
+ incref(up->egrp);
}
procfork(p);
poperror(); /* abortion */
+
+ if(flag & RFNOMNT)
+ devmask(p->pgrp, 1, nomntdevs);
if((flag&RFNOWAIT) == 0){
p->parent = up;
--
⑨