ref: 41261cc8c65e1d3931c68bad4fbdc65b66e939e1
parent: 93b906ab3b2a9ae4ed3b65430bd616e314f1c7e3
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;
--
⑨