shithub: rc

Download patch

ref: 3e907e648d7263c159c604dc51aa8ca5d5fcd7f8
parent: ab2af6895d0e66aa9e5a94f77c2ba132c08f28d8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jun 14 13:01:16 EDT 2025

rc: fix fn sigexit handling (thanks nepomuk)

The sigexit pseudo note handler was only ran when we
did a explicit exit call, not when returning from
the last thread.

Also, the exitnext() check in Xsimple() that  avoids
an extra fork/wait must take into account if we need
to run the sigexit handler, so add a trapexit() function
that tells if we need to run the handler and skip
the optimization when we have to.

--- a/exec.c
+++ b/exec.c
@@ -386,22 +386,27 @@
 	if(!truestatus()) Xexit();
 }
 
+static int trapped;
+
+var*
+trapexit(void)
+{
+	if(getpid()==mypid && !trapped){
+		var *trap = vlook("sigexit");
+		if(trap->fn)
+			return trap;
+	}
+	return (var*)0;
+}
+
 void
 Xexit(void)
 {
-	static int beenhere = 0;
-
-	if(getpid()==mypid && !beenhere){
-		var *trapreq = vlook("sigexit");
-		word *starval = vlook("*")->val;
-		if(trapreq->fn){
-			beenhere = 1;
-			--runq->pc;
-			startfunc(trapreq, copywords(starval, (word*)0), (var*)0, (redir*)0);
-			return;
-		}
-	}
-	Exit();
+	var *trap = trapexit();
+	if(trap==0) Exit();
+	if(runq) --runq->pc;
+	startfunc(trap, copywords(vlook("*")->val, (word*)0), (var*)0, (redir*)0);
+	trapped = 1;
 }
 
 void
@@ -591,7 +596,7 @@
 		Xpopredir();
 	popthread();
 	if(runq==0)
-		Exit();
+		Xexit();
 }
 
 void
--- a/fns.h
+++ b/fns.h
@@ -63,6 +63,7 @@
 void	setstatus(char*);
 void	skipnl(void);
 void	start(code*, int, var*, redir*);
+var*	trapexit(void);
 int	truestatus(void);
 void	usage(char*);
 int	wordchr(int);
--- a/simple.c
+++ b/simple.c
@@ -18,7 +18,7 @@
 loop:
 	c=&p->code[p->pc];
 	while(1){
-		if(c->f==Xpopredir || c->f==Xunlocal)
+		if(c->f==Xpopredir || c->f==Xunlocal || c->f==Xeflag)
 			c++;
 		else if(c->f==Xsrcline)
 			c += 2;
@@ -86,7 +86,7 @@
 			(*f)();
 			return;
 		}
-		if(exitnext()){
+		if(exitnext() && trapexit()==0){
 			/* fork and wait is redundant */
 			pushword("exec");
 			execexec();
--