EAGAIN on a blocking socket?
OK, for the benefit of others listening in, this is what I've briefly described to Steve and Anders on suse-linux-e - who both said "it's impossible" - which I agree with. Reality however seems to be of a different opinion. I'm writing a simple, multi-threaded SMTP proxy. New connections are received/accepted, packed into a unit-of-work, then queued for one of X worker-threads to pick up. Each UOW has the socket returned by the accept call. I refer to this as the "left side". When a UOW is picked up for processing, the thread will connect to the outbound side (the "right side"), and then start processing. Here's roughly what happens: (code attached) check that the socket is still valid - the client could have gone away whilst the UOW was queued. connect to right side (create socket etc.) create a copy of the socket - new one is called right2. The original is set nonblocking. Now create streams, one on each socket. Similar thing for the left side. The main code (not attached) now uses select() on the left and right inbound, nonblocking sockets, and when e.g. the left side has some data for us,: if ( FD_ISSET(left,&readfds) ) { closed=1; while( NULL!=fgets( buffer, sizeof(buffer), left_in ) ) { closed=0; while( EOF==(rc=fputs( buffer, right_out )) ) { if ( errno!=EAGAIN ) break; log_error( "[%02u.%04u] %d.2: unable to write to right; error %d: %s\n", c->id, work->id, stage, errno, strerror(errno) ); sleep(1); } if ( EOF==rc ) { stage=99; break; } } fflush( right_out ); // if the left side closed the connection if ( closed ) { log_error( "right side closed??\n"); stage=99; } } /Per Jessen, Zürich
participants (4)
-
Anders Johansson
-
Jerry Feldman
-
Per Jessen
-
Steve Graegert