From 5a8e63b2f016735364d17866d5e2bcb35d20c78b Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 29 Feb 2004 22:10:26 +0000 Subject: Fighting the good fight. Move libfmt, libutf into subdirectories of lib9. Add poll-based socket i/o to libthread, so that we can avoid using multiple procs when possible, thus removing dependence on crappy pthreads implementations. Convert samterm, acme to the single-proc libthread. Bring libcomplete, acme up-to-date w.r.t. Plan 9 distribution. --- src/libthread/exec-unix.c | 139 +++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 93 deletions(-) (limited to 'src/libthread/exec-unix.c') diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c index c04d414c..bfffa14d 100644 --- a/src/libthread/exec-unix.c +++ b/src/libthread/exec-unix.c @@ -2,28 +2,18 @@ #include #include "threadimpl.h" +static void efork(int[3], int[2], char*, char**); void -procexec(Channel *pidc, int fd[3], char *prog, char *args[]) +threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) { - int n; - Proc *p; - Thread *t; - - _threaddebug(DBGEXEC, "procexec %s", prog); - /* must be only thread in proc */ - p = _threadgetproc(); - t = p->thread; - if(p->threads.head != t || p->threads.head->nextt != nil){ - werrstr("not only thread in proc"); - Bad: - _threaddebug(DBGEXEC, "procexec bad %r"); - if(pidc) - sendul(pidc, ~0); - return; - } + int pfd[2]; + int n, pid; + char exitstr[ERRMAX]; + _threaddebug(DBGEXEC, "threadexec %s", prog); + /* - * We want procexec to behave like exec; if exec succeeds, + * We want threadexec to behave like exec; if exec succeeds, * never return, and if it fails, return with errstr set. * Unfortunately, the exec happens in another proc since * we have to wait for the exec'ed process to finish. @@ -34,114 +24,77 @@ procexec(Channel *pidc, int fd[3], char *prog, char *args[]) * then the proc doing the exec sends the errstr down the * pipe to us. */ - if(pipe(p->exec.fd) < 0) + if(pipe(pfd) < 0) goto Bad; - if(fcntl(p->exec.fd[0], F_SETFD, 1) < 0) + if(fcntl(pfd[0], F_SETFD, 1) < 0) goto Bad; - if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0) + if(fcntl(pfd[1], F_SETFD, 1) < 0) goto Bad; - /* exec in parallel via the scheduler */ - assert(p->needexec==0); - p->exec.prog = prog; - p->exec.args = args; - p->exec.stdfd = fd; - p->needexec = 1; - _sched(); + switch(pid = fork()){ + case -1: + close(pfd[0]); + close(pfd[1]); + goto Bad; + case 0: + efork(fd, pfd, prog, args); + _exit(0); + default: + break; + } - close(p->exec.fd[1]); - if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */ - p->exitstr[n] = '\0'; - errstr(p->exitstr, ERRMAX); - close(p->exec.fd[0]); + close(pfd[1]); + if((n = read(pfd[0], exitstr, ERRMAX-1)) > 0){ /* exec failed */ + exitstr[n] = '\0'; + errstr(exitstr, ERRMAX); + close(pfd[0]); goto Bad; } - close(p->exec.fd[0]); + close(pfd[0]); close(fd[0]); if(fd[1] != fd[0]) close(fd[1]); if(fd[2] != fd[1] && fd[2] != fd[0]) close(fd[2]); if(pidc) - sendul(pidc, t->ret); + sendul(pidc, pid); - _threaddebug(DBGEXEC, "procexec schedexecwait"); - /* wait for exec'ed program, then exit */ - _schedexecwait(); -} + _threaddebug(DBGEXEC, "threadexec schedexecwait"); + threadexits(0); -void -procexecl(Channel *pidc, int fd[3], char *f, ...) -{ - procexec(pidc, fd, f, &f+1); +Bad: + _threaddebug(DBGEXEC, "threadexec bad %r"); + if(pidc) + sendul(pidc, ~0); } void -_schedexecwait(void) +threadexecl(Channel *pidc, int fd[3], char *f, ...) { - int pid; - Channel *c; - Proc *p; - Thread *t; - Waitmsg *w; - - p = _threadgetproc(); - t = p->thread; - pid = t->ret; - _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret); - - for(;;){ - w = wait(); - if(w == nil) - break; - if(w->pid == pid) - break; - free(w); - } - if(w != nil){ - if((c = _threadwaitchan) != nil) - sendp(c, w); - else - free(w); - } - threadexits("procexec"); + threadexec(pidc, fd, f, &f+1); } static void -efork(void *ve) +efork(int stdfd[3], int fd[2], char *prog, char **args) { char buf[ERRMAX]; - Execargs *e; int i; - e = ve; - _threaddebug(DBGEXEC, "_schedexec %s -- calling execv", e->prog); - dup(e->stdfd[0], 0); - dup(e->stdfd[1], 1); - dup(e->stdfd[2], 2); + _threaddebug(DBGEXEC, "_schedexec %s -- calling execv", prog); + dup(stdfd[0], 0); + dup(stdfd[1], 1); + dup(stdfd[2], 2); for(i=3; i<40; i++) - if(i != e->fd[1]) + if(i != fd[1]) close(i); rfork(RFNOTEG); - execvp(e->prog, e->args); + execvp(prog, args); _threaddebug(DBGEXEC, "_schedexec failed: %r"); rerrstr(buf, sizeof buf); if(buf[0]=='\0') strcpy(buf, "exec failed"); - write(e->fd[1], buf, strlen(buf)); - close(e->fd[1]); + write(fd[1], buf, strlen(buf)); + close(fd[1]); _exits(buf); } -int -_schedexec(Execargs *e) -{ - int pid; - - pid = fork(); - if(pid == 0){ - efork(e); - _exit(1); - } - return pid; -} -- cgit v1.2.3