Blob
- Date:
- Message:
- rc: fix segfault when SIGINT is received Save the value of `runq' at the start of the function, so that the `pc' update at the end does work on that original value, and not on a probably modified value of `runq'. fixes #14 http://code.swtch.com/plan9port/issue/14/ http://codereview.appspot.com/104066
- Actions:
- History | Blame | Raw File
1 #include <u.h>2 #include <signal.h>3 #if defined(PLAN9PORT) && defined(__sun__)4 # define BSD_COMP /* sigh. for TIOCNOTTY */5 #endif6 #include <sys/ioctl.h>7 #include "rc.h"8 #include "getflags.h"9 #include "exec.h"10 #include "io.h"11 #include "fns.h"13 int havefork = 1;15 void16 Xasync(void)17 {18 int null = open("/dev/null", 0);19 int tty;20 int pid;21 char npid[10];22 if(null<0){23 Xerror("Can't open /dev/null\n");24 return;25 }26 switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){27 case -1:28 close(null);29 Xerror("try again");30 break;31 case 0:32 clearwaitpids();33 /*34 * I don't know what the right thing to do here is,35 * so this is all experimentally determined.36 * If we just dup /dev/null onto 0, then running37 * ssh foo & will reopen /dev/tty, try to read a password,38 * get a signal, and repeat, in a tight loop, forever.39 * Arguably this is a bug in ssh (it behaves the same40 * way under bash as under rc) but I'm fixing it here41 * anyway. If we dissociate the process from the tty,42 * then it won't be able to open /dev/tty ever again.43 * The SIG_IGN on SIGTTOU makes writing the tty44 * (via fd 1 or 2, for example) succeed even though45 * our pgrp is not the terminal's controlling pgrp.46 */47 if((tty = open("/dev/tty", OREAD)) >= 0){48 /*49 * Should make reads of tty fail, writes succeed.50 */51 signal(SIGTTIN, SIG_IGN);52 signal(SIGTTOU, SIG_IGN);53 ioctl(tty, TIOCNOTTY);54 close(tty);55 }56 if(isatty(0))57 pushredir(ROPEN, null, 0);58 else59 close(null);60 start(runq->code, runq->pc+1, runq->local);61 runq->ret = 0;62 break;63 default:64 addwaitpid(pid);65 close(null);66 runq->pc = runq->code[runq->pc].i;67 inttoascii(npid, pid);68 setvar("apid", newword(npid, (word *)0));69 break;70 }71 }73 void74 Xpipe(void)75 {76 struct thread *p = runq;77 int pc = p->pc, forkid;78 int lfd = p->code[pc++].i;79 int rfd = p->code[pc++].i;80 int pfd[2];81 if(pipe(pfd)<0){82 Xerror("can't get pipe");83 return;84 }85 switch(forkid = fork()){86 case -1:87 Xerror("try again");88 break;89 case 0:90 clearwaitpids();91 start(p->code, pc+2, runq->local);92 runq->ret = 0;93 close(pfd[PRD]);94 pushredir(ROPEN, pfd[PWR], lfd);95 break;96 default:97 addwaitpid(forkid);98 start(p->code, p->code[pc].i, runq->local);99 close(pfd[PWR]);100 pushredir(ROPEN, pfd[PRD], rfd);101 p->pc = p->code[pc+1].i;102 p->pid = forkid;103 break;104 }105 }107 /*108 * Who should wait for the exit from the fork?109 */110 void111 Xbackq(void)112 {113 struct thread *p = runq;114 char wd[8193];115 int c;116 char *s, *ewd=&wd[8192], *stop;117 struct io *f;118 var *ifs = vlook("ifs");119 word *v, *nextv;120 int pfd[2];121 int pid;122 stop = ifs->val?ifs->val->word:"";123 if(pipe(pfd)<0){124 Xerror("can't make pipe");125 return;126 }127 switch(pid = fork()){128 case -1:129 Xerror("try again");130 close(pfd[PRD]);131 close(pfd[PWR]);132 return;133 case 0:134 clearwaitpids();135 close(pfd[PRD]);136 start(runq->code, runq->pc+1, runq->local);137 pushredir(ROPEN, pfd[PWR], 1);138 return;139 default:140 addwaitpid(pid);141 close(pfd[PWR]);142 f = openfd(pfd[PRD]);143 s = wd;144 v = 0;145 while((c = rchr(f))!=EOF){146 if(strchr(stop, c) || s==ewd){147 if(s!=wd){148 *s='\0';149 v = newword(wd, v);150 s = wd;151 }152 }153 else *s++=c;154 }155 if(s!=wd){156 *s='\0';157 v = newword(wd, v);158 }159 closeio(f);160 Waitfor(pid, 0);161 /* v points to reversed arglist -- reverse it onto argv */162 while(v){163 nextv = v->next;164 v->next = runq->argv->words;165 runq->argv->words = v;166 v = nextv;167 }168 p->pc = p->code[p->pc].i;169 return;170 }171 }173 void174 Xpipefd(void)175 {176 struct thread *p = runq;177 int pc = p->pc, pid;178 char name[40];179 int pfd[2];180 int sidefd, mainfd;181 if(pipe(pfd)<0){182 Xerror("can't get pipe");183 return;184 }185 if(p->code[pc].i==READ){186 sidefd = pfd[PWR];187 mainfd = pfd[PRD];188 }189 else{190 sidefd = pfd[PRD];191 mainfd = pfd[PWR];192 }193 switch(pid = fork()){194 case -1:195 Xerror("try again");196 break;197 case 0:198 clearwaitpids();199 start(p->code, pc+2, runq->local);200 close(mainfd);201 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);202 runq->ret = 0;203 break;204 default:205 addwaitpid(pid);206 close(sidefd);207 pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */208 strcpy(name, Fdprefix);209 inttoascii(name+strlen(name), mainfd);210 pushword(name);211 p->pc = p->code[pc+1].i;212 break;213 }214 }216 void217 Xsubshell(void)218 {219 int pid;220 switch(pid = fork()){221 case -1:222 Xerror("try again");223 break;224 case 0:225 clearwaitpids();226 start(runq->code, runq->pc+1, runq->local);227 runq->ret = 0;228 break;229 default:230 addwaitpid(pid);231 Waitfor(pid, 1);232 runq->pc = runq->code[runq->pc].i;233 break;234 }235 }237 int238 execforkexec(void)239 {240 int pid;241 int n;242 char buf[ERRMAX];244 switch(pid = fork()){245 case -1:246 return -1;247 case 0:248 clearwaitpids();249 pushword("exec");250 execexec();251 strcpy(buf, "can't exec: ");252 n = strlen(buf);253 errstr(buf+n, ERRMAX-n);254 Exit(buf);255 }256 addwaitpid(pid);257 return pid;258 }