summaryrefslogtreecommitdiffstats
path: root/src/libthread/exec-unix.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-02-29 22:10:26 +0000
committerrsc <devnull@localhost>2004-02-29 22:10:26 +0000
commit5a8e63b2f016735364d17866d5e2bcb35d20c78b (patch)
treed5d0ce11e087efaf81c77311bac9d30aed41783d /src/libthread/exec-unix.c
parentd51419bf4397cf13d0c50bf84c125477c6bed307 (diff)
downloadplan9port-5a8e63b2f016735364d17866d5e2bcb35d20c78b.tar.gz
plan9port-5a8e63b2f016735364d17866d5e2bcb35d20c78b.zip
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.
Diffstat (limited to 'src/libthread/exec-unix.c')
-rw-r--r--src/libthread/exec-unix.c139
1 files changed, 46 insertions, 93 deletions
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 <unistd.h>
#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;
-}