comparison common-channel.c @ 652:17962b2a6b8f

- Make sure we don't use channel-specific data after it has been freed with a ChanType->closehandler()
author Matt Johnston <matt@ucc.asn.au>
date Sun, 04 Dec 2011 05:27:29 +0800
parents a98a2138364a
children c519b78b6d1a
comparison
equal deleted inserted replaced
651:a48a1f6ab43e 652:17962b2a6b8f
136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); 136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
137 newchan->type = type; 137 newchan->type = type;
138 newchan->index = i; 138 newchan->index = i;
139 newchan->sent_close = newchan->recv_close = 0; 139 newchan->sent_close = newchan->recv_close = 0;
140 newchan->sent_eof = newchan->recv_eof = 0; 140 newchan->sent_eof = newchan->recv_eof = 0;
141 newchan->close_handler_done = 0;
141 142
142 newchan->remotechan = remotechan; 143 newchan->remotechan = remotechan;
143 newchan->transwindow = transwindow; 144 newchan->transwindow = transwindow;
144 newchan->transmaxpacket = transmaxpacket; 145 newchan->transmaxpacket = transmaxpacket;
145 146
268 channel->errfd, channel->sent_close, channel->recv_close)) 269 channel->errfd, channel->sent_close, channel->recv_close))
269 TRACE(("writebuf size %d extrabuf size %d", 270 TRACE(("writebuf size %d extrabuf size %d",
270 cbuf_getused(channel->writebuf), 271 cbuf_getused(channel->writebuf),
271 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) 272 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
272 273
273 if (!channel->flushing && channel->type->check_close 274 if (!channel->flushing
275 && !channel->close_handler_done
276 && channel->type->check_close
274 && channel->type->check_close(channel)) 277 && channel->type->check_close(channel))
275 { 278 {
276 channel->flushing = 1; 279 channel->flushing = 1;
277 } 280 }
278 281
279 /* if a type-specific check_close is defined we will only exit 282 /* if a type-specific check_close is defined we will only exit
280 once that has been triggered. this is only used for a server "session" 283 once that has been triggered. this is only used for a server "session"
281 channel, to ensure that the shell has exited (and the exit status 284 channel, to ensure that the shell has exited (and the exit status
282 retrieved) before we close things up. */ 285 retrieved) before we close things up. */
283 if (!channel->type->check_close 286 if (!channel->type->check_close
284 || channel->type->check_close(channel)) { 287 || channel->close_handler_done
288 || channel->type->check_close(channel)) {
285 close_allowed = 1; 289 close_allowed = 1;
286 } 290 }
287 291
288 if (channel->recv_close && !write_pending(channel) && close_allowed) { 292 if (channel->recv_close && !write_pending(channel) && close_allowed) {
289 if (!channel->sent_close) { 293 if (!channel->sent_close) {
361 365
362 366
363 /* Send the close message and set the channel as closed */ 367 /* Send the close message and set the channel as closed */
364 static void send_msg_channel_close(struct Channel *channel) { 368 static void send_msg_channel_close(struct Channel *channel) {
365 369
366 TRACE(("enter send_msg_channel_close")) 370 TRACE(("enter send_msg_channel_close %p", channel))
367 if (channel->type->closehandler) { 371 if (channel->type->closehandler
372 && !channel->close_handler_done) {
368 channel->type->closehandler(channel); 373 channel->type->closehandler(channel);
374 channel->close_handler_done = 1;
369 } 375 }
370 376
371 CHECKCLEARTOWRITE(); 377 CHECKCLEARTOWRITE();
372 378
373 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); 379 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
566 * such as chansession or x11fwd */ 572 * such as chansession or x11fwd */
567 void recv_msg_channel_request() { 573 void recv_msg_channel_request() {
568 574
569 struct Channel *channel; 575 struct Channel *channel;
570 576
571 TRACE(("enter recv_msg_channel_request"))
572
573 channel = getchannel(); 577 channel = getchannel();
578
579 TRACE(("enter recv_msg_channel_request %p", channel))
574 580
575 if (channel->sent_close) { 581 if (channel->sent_close) {
576 TRACE(("leave recv_msg_channel_request: already closed channel")) 582 TRACE(("leave recv_msg_channel_request: already closed channel"))
577 return; 583 return;
578 } 584 }
579 585
580 if (channel->type->reqhandler) { 586 if (channel->type->reqhandler
587 && !channel->close_handler_done) {
581 channel->type->reqhandler(channel); 588 channel->type->reqhandler(channel);
582 } else { 589 } else {
583 send_msg_channel_failure(channel); 590 send_msg_channel_failure(channel);
584 } 591 }
585 592