| @@ -0,0 +1,74 @@ |
| 1 | +#include <u.h> |
| 2 | +#include <libc.h> |
| 3 | +#include <thread.h> |
| 4 | + |
| 5 | +typedef struct Exec Exec; |
| 6 | + |
| 7 | +struct Exec { |
| 8 | + /* these two specify what program (and arguments) to run using procexec */ |
| 9 | + char *file; |
| 10 | + char **argv; |
| 11 | + |
| 12 | + /* this will have either -1 or the actual pid of the executed program sent over */ |
| 13 | + Channel *pid; |
| 14 | +}; |
| 15 | + |
| 16 | +void |
| 17 | +pexec(void *args) |
| 18 | +{ |
| 19 | + Exec *e = args; |
| 20 | + procexec(e->pid, e->file, e->argv); |
| 21 | +} |
| 22 | + |
| 23 | +void |
| 24 | +threadmain(int, char **) |
| 25 | +{ |
| 26 | + Exec e; |
| 27 | + int i, n, pid; |
| 28 | + Channel *waitc; |
| 29 | + Waitmsg *w; |
| 30 | + char *argv[] = {"rc", "-c", "sleep 2", nil}; |
| 31 | + |
| 32 | + quotefmtinstall(); |
| 33 | + |
| 34 | + /* this HAS to be called before spawning other threads |
| 35 | + * otherwise those threads won't send their status |
| 36 | + */ |
| 37 | + waitc = threadwaitchan(); |
| 38 | + |
| 39 | + /* that's where we get the pid from */ |
| 40 | + e.pid = chancreate(sizeof(int), 0); |
| 41 | + |
| 42 | + for(n = i = 0; i < 3; n++, i++){ |
| 43 | + /* last process always fails to demonstrate the error status */ |
| 44 | + if(i == 2) |
| 45 | + argv[2] = "this breaks"; |
| 46 | + e.file = "/bin/rc"; |
| 47 | + e.argv = argv; |
| 48 | + proccreate(pexec, &e, 4096); |
| 49 | + |
| 50 | + /* receive the pid */ |
| 51 | + recv(e.pid, &pid); |
| 52 | + if(pid < 0) |
| 53 | + sysfatal("procexec failed"); |
| 54 | + |
| 55 | + fprint(2, "pid %d running\n", pid); |
| 56 | + } |
| 57 | + |
| 58 | + /* won't get any new pids at this point */ |
| 59 | + chanfree(e.pid); |
| 60 | + |
| 61 | + /* wait until all processes are finished |
| 62 | + * we know how many there are so it's pretty easy |
| 63 | + */ |
| 64 | + while(n > 0){ |
| 65 | + /* w (Waitmsg) points to the result of a finished process */ |
| 66 | + w = recvp(waitc); |
| 67 | + fprint(2, "pid %d: %q\n", w->pid, w->msg); |
| 68 | + /* each one of them is allocated with malloc */ |
| 69 | + free(w); |
| 70 | + n--; |
| 71 | + } |
| 72 | + |
| 73 | + threadexitsall(nil); |
| 74 | +} |