From 7e1eaee616365799cfc4cc787fdaa9448958536b Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 20 Oct 2021 14:21:06 -0700 Subject: Feat: now execs instead of exec + fork if going to exit. One quick solution to the lack of tracking deep into the command line is to note that the pattern of code emitted for an async is: Xasync |__ child (command) |__ parent (continues) The child creates a process group, as described before. If the child is a simple command, we will now "exec" as it will exit immediately after the command. This gives us the correct behavior, at least for simple cases. This also fixed pipes. However, if child has to be forked, i.e. can't be immediately execed, then I don't think this process works... --- sys/cmd/rc/exec.c | 25 +++++++++++++++++++++---- sys/cmd/rc/lex.c | 2 +- sys/cmd/rc/sys.c | 2 ++ sys/cmd/rc/wait.c | 22 ++++++++++++++++++++-- 4 files changed, 44 insertions(+), 7 deletions(-) (limited to 'sys/cmd') diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index f9af866..eede516 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -150,6 +150,17 @@ undoredirs(void) Xpopredir(); } +static inline +int +exitsnext(void) +{ + Code *c = &runner->code.exe[runner->code.i]; + while(c->f == Xpopredir) + c++; + + return c->f == Xexit; +} + static inline void defaultsignal(void) @@ -507,8 +518,8 @@ xfg(void) poplist(); // this goes here? wakeup(job); - foreground(job, 1); job->caller = runner, runner = job; // XXX: can this leave zombies? + foreground(job, 1); } void @@ -778,7 +789,7 @@ Xpipe(void) initchild(runner,1); /* child 0 (writer) forked process */ - run(runner->code.exe, pc+2, runner->local, 0); + run(runner->code.exe, pc+2, runner->local, 1); runner->caller = nil; close(pfd[0]); @@ -789,10 +800,12 @@ Xpipe(void) initparent(runner,pid,0); /* child 1 (reader) subprocess*/ - run(runner->code.exe, runner->code.exe[pc].i, runner->local, 0); + run(runner->code.exe, runner->code.exe[pc].i, runner->local, 1); close(pfd[1]); pushredir(Ropen, pfd[0], rfd); + + orig->code.i = orig->code.exe[pc+1].i; break; } } @@ -825,7 +838,11 @@ Xbasic(void) } /* if we are here then it's an external command */ - // TODO: check for if we will exit, don't need to fork, just exec + if(exitsnext()){ // if we exit immediately, no need to fork + pushword("exec"); + xx(); + Xexit(); + } // run the external command if((pid = xforkx()) < 0) { diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c index 373edd5..eb3a268 100644 --- a/sys/cmd/rc/lex.c +++ b/sys/cmd/rc/lex.c @@ -209,7 +209,7 @@ yylex(void) node->type = Tpipe; node->redir.fd[0] = 1; - node->redir.fd[1] = 1; + node->redir.fd[1] = 0; goto redir; case '>': diff --git a/sys/cmd/rc/sys.c b/sys/cmd/rc/sys.c index 496c2e6..a24545f 100644 --- a/sys/cmd/rc/sys.c +++ b/sys/cmd/rc/sys.c @@ -99,6 +99,8 @@ redirect(Redir *r) switch(r->type){ case Ropen: if(r->from != r->to){ + dup2(r->from, r->to); + close(r->from); } break; case Rdup: diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c index 4d45e4b..911601c 100644 --- a/sys/cmd/rc/wait.c +++ b/sys/cmd/rc/wait.c @@ -27,6 +27,10 @@ await(int pid4, int opt, struct WaitMsg *msg) /* event loop */ for(;;){ if((pid = wait4(pid4, &status, opt, &ru)) <= 0){ + if(errno == ECHILD){ + msg->pid = -1; + return 1; + } msg->pid = 0; perror("failed wait4"); return 0; @@ -168,9 +172,16 @@ waitall(Thread *job) struct WaitMsg msg; while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){ - if(msg.pid == 0){ + switch(msg.pid){ + case 0: // error perror("wait job"); return 0; + case -1: // no children: assume they have exited + job->wait.status = Pdone; + clearwait(job); + return 1; + default: + ; } notify(job, msg); @@ -186,9 +197,16 @@ waitfor(Thread *job, int pid) struct WaitMsg msg; while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){ - if(msg.pid == 0){ + switch(msg.pid){ + case 0: // error perror("wait for"); return 0; + case -1: // no children: assume they have exited + job->wait.status = Pdone; + clearwait(job); + return 1; + default: + ; } notify(job, msg); -- cgit v1.2.1