comparison common-channel.c @ 376:4f2dbd1c3685 channel-fix

Add some code for testing whether a writefd is closed (by read()ing from it)
author Matt Johnston <matt@ucc.asn.au>
date Tue, 05 Dec 2006 15:23:06 +0000
parents 8d149b812669
children a5bca950120d c53a26c430e5
comparison
equal deleted inserted replaced
375:8d149b812669 376:4f2dbd1c3685
184 184
185 struct Channel* getchannel() { 185 struct Channel* getchannel() {
186 return getchannel_msg(NULL); 186 return getchannel_msg(NULL);
187 } 187 }
188 188
189 /* In order to tell if a writefd is closed, we put it in the readfd FD_SET.
190 We then just try reading a single byte from it. It'll give EAGAIN or something
191 if the socket is still alive (but the FD probably shouldn't be set anyway?)*/
192 static void check_closed_writefd(struct Channel* channel, int fd) {
193 char c;
194 int ret;
195 TRACE(("enter check_closed_writefd fd %d", fd))
196 if (fd < 0) {
197 TRACE(("leave check_closed_writefd."))
198 return;
199 }
200
201 /* Read something. doing read(fd,x,0) seems to become a NOP on some platforms */
202 ret = read(fd, &c, 1);
203 TRACE(("ret %d errno %d", ret, errno))
204 if (ret > 0 || (ret < 0 && (errno == EINTR || errno == EAGAIN))) {
205 TRACE(("leave check_closed_writefd"))
206 return;
207 }
208 close_chan_fd(channel, fd, SHUT_WR);
209 TRACE(("leave check_closed_writefd after closing %d", fd))
210 }
211
189 /* Iterate through the channels, performing IO if available */ 212 /* Iterate through the channels, performing IO if available */
190 void channelio(fd_set *readfds, fd_set *writefds) { 213 void channelio(fd_set *readfds, fd_set *writefds) {
191 214
192 struct Channel *channel; 215 struct Channel *channel;
193 unsigned int i; 216 unsigned int i;
226 /* stderr for client mode */ 249 /* stderr for client mode */
227 if (ERRFD_IS_WRITE(channel) 250 if (ERRFD_IS_WRITE(channel)
228 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) { 251 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
229 writechannel(channel, channel->errfd, channel->extrabuf); 252 writechannel(channel, channel->errfd, channel->extrabuf);
230 } 253 }
254
255 /* Check writefds for close, even if we don't have anything
256 to write into them. */
257 if (channel->writefd >= 0) {
258 check_closed_writefd(channel, channel->writefd);
259 }
260 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0) {
261 check_closed_writefd(channel, channel->errfd);
262 }
263
231 264
232 /* handle any channel closing etc */ 265 /* handle any channel closing etc */
233 check_close(channel); 266 check_close(channel);
234 267
235 } 268 }
437 if (ERRFD_IS_WRITE(channel) != NULL && channel->errfd >= 0 470 if (ERRFD_IS_WRITE(channel) != NULL && channel->errfd >= 0
438 && cbuf_getused(channel->extrabuf) > 0 ) { 471 && cbuf_getused(channel->extrabuf) > 0 ) {
439 FD_SET(channel->errfd, writefds); 472 FD_SET(channel->errfd, writefds);
440 } 473 }
441 474
475 /* We also set the writefds for reading, so that we will be notified of close */
476 if (channel->writefd >= 0) {
477 FD_SET(channel->writefd, readfds);
478 }
479 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0) {
480 FD_SET(channel->errfd, readfds);
481 }
482
483
484
442 } /* foreach channel */ 485 } /* foreach channel */
443 486
444 #ifdef USING_LISTENERS 487 #ifdef USING_LISTENERS
445 set_listener_fds(readfds); 488 set_listener_fds(readfds);
446 #endif 489 #endif