comparison svr-chansession.c @ 423:b2b67cfcd66e channel-fix

- Fix bug in child-exit handling where the wrong pid was being matched. - Also wait for errfd to close before closing the channel
author Matt Johnston <matt@ucc.asn.au>
date Mon, 12 Feb 2007 10:39:22 +0000
parents a01c0c8e543a
children 5df05d0a5366
comparison
equal deleted inserted replaced
422:a9e0ddac5ba7 423:b2b67cfcd66e
65 /* required to clear environment */ 65 /* required to clear environment */
66 extern char** environ; 66 extern char** environ;
67 67
68 static int sesscheckclose(struct Channel *channel) { 68 static int sesscheckclose(struct Channel *channel) {
69 struct ChanSess *chansess = (struct ChanSess*)channel->typedata; 69 struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
70 TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
70 return chansess->exit.exitpid != -1; 71 return chansess->exit.exitpid != -1;
71 } 72 }
72 73
73 /* Handler for childs exiting, store the state for return to the client */ 74 /* Handler for childs exiting, store the state for return to the client */
74 75
86 struct sigaction sa_chld; 87 struct sigaction sa_chld;
87 struct exitinfo *exit = NULL; 88 struct exitinfo *exit = NULL;
88 89
89 TRACE(("enter sigchld handler")) 90 TRACE(("enter sigchld handler"))
90 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 91 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
92 TRACE(("sigchld handler: pid %d", pid))
91 93
92 exit = NULL; 94 exit = NULL;
93 /* find the corresponding chansess */ 95 /* find the corresponding chansess */
94 for (i = 0; i < svr_ses.childpidsize; i++) { 96 for (i = 0; i < svr_ses.childpidsize; i++) {
95 if (svr_ses.childpids[i].pid == pid) { 97 if (svr_ses.childpids[i].pid == pid) {
96 98 TRACE(("found match session"));
97 exit = &svr_ses.childpids[i].chansess->exit; 99 exit = &svr_ses.childpids[i].chansess->exit;
98 break; 100 break;
99 } 101 }
100 } 102 }
101 103
102 /* If the pid wasn't matched, then we might have hit the race mentioned 104 /* If the pid wasn't matched, then we might have hit the race mentioned
103 * above. So we just store the info for the parent to deal with */ 105 * above. So we just store the info for the parent to deal with */
104 if (exit == NULL) { 106 if (exit == NULL) {
107 TRACE(("using lastexit"));
105 exit = &svr_ses.lastexit; 108 exit = &svr_ses.lastexit;
106 } 109 }
107 110
108 exit->exitpid = pid; 111 exit->exitpid = pid;
109 if (WIFEXITED(status)) { 112 if (WIFEXITED(status)) {
123 126
124 /* Make sure that the main select() loop wakes up */ 127 /* Make sure that the main select() loop wakes up */
125 while (1) { 128 while (1) {
126 /* EAGAIN means the pipe's full, so don't need to write anything */ 129 /* EAGAIN means the pipe's full, so don't need to write anything */
127 /* isserver is just a random byte to write */ 130 /* isserver is just a random byte to write */
128 if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1 || errno == EAGAIN) { 131 if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
132 || errno == EAGAIN) {
129 break; 133 break;
130 } 134 }
131 if (errno == EINTR) { 135 if (errno == EINTR) {
132 continue; 136 continue;
133 } 137 }
140 sigaction(SIGCHLD, &sa_chld, NULL); 144 sigaction(SIGCHLD, &sa_chld, NULL);
141 TRACE(("leave sigchld handler")) 145 TRACE(("leave sigchld handler"))
142 } 146 }
143 147
144 /* send the exit status or the signal causing termination for a session */ 148 /* send the exit status or the signal causing termination for a session */
145 /* XXX server */
146 static void send_exitsignalstatus(struct Channel *channel) { 149 static void send_exitsignalstatus(struct Channel *channel) {
147 150
148 struct ChanSess *chansess = (struct ChanSess*)channel->typedata; 151 struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
149 152
150 if (chansess->exit.exitpid >= 0) { 153 if (chansess->exit.exitpid >= 0) {
179 static void send_msg_chansess_exitsignal(struct Channel * channel, 182 static void send_msg_chansess_exitsignal(struct Channel * channel,
180 struct ChanSess * chansess) { 183 struct ChanSess * chansess) {
181 184
182 int i; 185 int i;
183 char* signame = NULL; 186 char* signame = NULL;
184
185 dropbear_assert(chansess->exit.exitpid != -1); 187 dropbear_assert(chansess->exit.exitpid != -1);
186 dropbear_assert(chansess->exit.exitsignal > 0); 188 dropbear_assert(chansess->exit.exitsignal > 0);
189
190 TRACE(("send_msg_chansess_exitsignal %d", chansess->exit.exitsignal))
187 191
188 CHECKCLEARTOWRITE(); 192 CHECKCLEARTOWRITE();
189 193
190 /* we check that we can match a signal name, otherwise 194 /* we check that we can match a signal name, otherwise
191 * don't send anything */ 195 * don't send anything */
292 /* clear child pid entries */ 296 /* clear child pid entries */
293 for (i = 0; i < svr_ses.childpidsize; i++) { 297 for (i = 0; i < svr_ses.childpidsize; i++) {
294 if (svr_ses.childpids[i].chansess == chansess) { 298 if (svr_ses.childpids[i].chansess == chansess) {
295 dropbear_assert(svr_ses.childpids[i].pid > 0); 299 dropbear_assert(svr_ses.childpids[i].pid > 0);
296 TRACE(("closing pid %d", svr_ses.childpids[i].pid)) 300 TRACE(("closing pid %d", svr_ses.childpids[i].pid))
297 TRACE(("exitpid = %d", chansess->exit.exitpid)) 301 TRACE(("exitpid is %d", chansess->exit.exitpid))
298 svr_ses.childpids[i].pid = -1; 302 svr_ses.childpids[i].pid = -1;
299 svr_ses.childpids[i].chansess = NULL; 303 svr_ses.childpids[i].chansess = NULL;
300 } 304 }
301 } 305 }
302 306
680 684
681 } else { 685 } else {
682 /* parent */ 686 /* parent */
683 TRACE(("continue noptycommand: parent")) 687 TRACE(("continue noptycommand: parent"))
684 chansess->pid = pid; 688 chansess->pid = pid;
689 TRACE(("child pid is %d", pid))
685 690
686 addchildpid(chansess, pid); 691 addchildpid(chansess, pid);
687 692
688 if (svr_ses.lastexit.exitpid != -1) { 693 if (svr_ses.lastexit.exitpid != -1) {
694 TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
689 /* The child probably exited and the signal handler triggered 695 /* The child probably exited and the signal handler triggered
690 * possibly before we got around to adding the childpid. So we fill 696 * possibly before we got around to adding the childpid. So we fill
691 * out it's data manually */ 697 * out its data manually */
692 for (i = 0; i < svr_ses.childpidsize; i++) { 698 for (i = 0; i < svr_ses.childpidsize; i++) {
693 if (svr_ses.childpids[i].pid == pid) { 699 if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
700 TRACE(("found match for lastexitpid"))
694 svr_ses.childpids[i].chansess->exit = svr_ses.lastexit; 701 svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
695 svr_ses.lastexit.exitpid = -1; 702 svr_ses.lastexit.exitpid = -1;
696 } 703 }
697 } 704 }
698 } 705 }
699
700 706
701 close(infds[FDIN]); 707 close(infds[FDIN]);
702 close(outfds[FDOUT]); 708 close(outfds[FDOUT]);
703 close(errfds[FDOUT]); 709 close(errfds[FDOUT]);
704 channel->writefd = infds[FDOUT]; 710 channel->writefd = infds[FDOUT];