properly handle accept returning EAGAIN or EINTR

cvs
Slava Pestov 2005-06-18 20:42:49 +00:00
parent d39f686e3e
commit e74577120b
2 changed files with 47 additions and 31 deletions

View File

@ -75,8 +75,12 @@ M: port set-timeout ( timeout port -- )
: pending-error ( reader -- ) port-error throw ; : pending-error ( reader -- ) port-error throw ;
: postpone-error ( reader -- ) : EAGAIN 35 ;
err_no strerror swap set-port-error ; : EINTR 4 ;
: postpone-error ( port -- )
err_no dup EAGAIN = over EINTR = or
[ 2drop ] [ strerror swap set-port-error ] ifte ;
! Associates a port with a list of continuations waiting on the ! Associates a port with a list of continuations waiting on the
! port to finish I/O ! port to finish I/O
@ -116,14 +120,15 @@ GENERIC: task-container ( task -- vector )
port-cutoff dup 0 = not swap millis < and ; port-cutoff dup 0 = not swap millis < and ;
: handle-fd? ( fdset task -- ? ) : handle-fd? ( fdset task -- ? )
dup io-task-port timeout? dup io-task-port timeout? [
[
2drop t 2drop t
] [ ] [
io-task-fd swap 2dup bit-nth io-task-fd swap 2dup bit-nth
>r f -rot set-bit-nth r> >r f -rot set-bit-nth r>
] ifte ; ] ifte ;
: debug-out 14 getenv fwrite ;
: handle-fdset ( fdset tasks -- ) : handle-fdset ( fdset tasks -- )
[ [
cdr tuck handle-fd? [ handle-fd ] [ drop ] ifte cdr tuck handle-fd? [ handle-fd ] [ drop ] ifte
@ -212,10 +217,12 @@ C: reader ( handle -- reader )
drop drop
] ifte t swap set-reader-ready? ; ] ifte t swap set-reader-ready? ;
: (refill) ( port -- n )
>port< tuck dup buffer-end swap buffer-capacity read ;
: refill ( port -- ) : refill ( port -- )
dup buffer-length 0 = [ dup buffer-length 0 = [
>port< (refill)
tuck dup buffer-end swap buffer-capacity read
dup 0 >= [ swap n>buffer ] [ drop postpone-error ] ifte dup 0 >= [ swap n>buffer ] [ drop postpone-error ] ifte
] [ ] [
drop drop

View File

@ -49,12 +49,44 @@ USING: alien generic kernel math unix-internals ;
dup 0 >= [ drop 1 listen ] [ ( fd n - n) nip ] ifte dup 0 >= [ drop 1 listen ] [ ( fd n - n) nip ] ifte
] with-socket-fd ; ] with-socket-fd ;
IN: streams
C: client-stream ( host port fd -- stream )
[ >r <socket-stream> r> set-delegate ] keep
[ set-client-stream-port ] keep
[ set-client-stream-host ] keep ;
: <client> ( host port -- stream )
#! Connect to a port number on a TCP/IP host.
client-socket <socket-stream> ;
TUPLE: server client ;
C: server ( port -- server )
#! Starts listening for TCP connections on localhost:port.
[ >r server-socket 0 <port> r> set-delegate ] keep ;
IN: io-internals
USE: unix-internals
TUPLE: accept-task ; TUPLE: accept-task ;
C: accept-task ( port -- task ) C: accept-task ( port -- task )
[ >r <io-task> r> set-delegate ] keep ; [ >r <io-task> r> set-delegate ] keep ;
M: accept-task do-io-task ( task -- ? ) drop t ; : init-socket ( fd -- ) SOL_SOCKET SO_OOBINLINE sockopt ;
: do-accept ( port sockaddr fd -- )
[
init-socket
dup sockaddr-in-addr inet-ntoa
swap sockaddr-in-port ntohs
] keep <client-stream> swap set-server-client ;
M: accept-task do-io-task ( task -- ? )
io-task-port <sockaddr-in>
over port-handle over "sockaddr-in" c-size <int> accept
dup 0 >= [ do-accept t ] [ 2drop postpone-error f ] ifte ;
M: accept-task task-container drop read-tasks get ; M: accept-task task-container drop read-tasks get ;
@ -69,12 +101,6 @@ M: accept-task task-container drop read-tasks get ;
HEX: ff bitand unparse % HEX: ff bitand unparse %
] make-string ; ] make-string ;
: do-accept ( fd -- fd host port )
<sockaddr-in>
[ "sockaddr-in" c-size <int> accept dup io-error ] keep
dup sockaddr-in-addr inet-ntoa
swap sockaddr-in-port ntohs ;
: <socket-stream> ( fd -- stream ) : <socket-stream> ( fd -- stream )
dup f <fd-stream> ; dup f <fd-stream> ;
@ -83,23 +109,6 @@ M: accept-task task-container drop read-tasks get ;
IN: streams IN: streams
C: client-stream ( fd host port -- stream )
[ set-client-stream-port ] keep
[ set-client-stream-host ] keep
[
>r
dup SOL_SOCKET SO_OOBINLINE sockopt
<socket-stream> r> set-delegate
] keep ;
: <client> ( host port -- stream )
#! Connect to a port number on a TCP/IP host.
client-socket <socket-stream> ;
: <server> ( port -- server )
#! Starts listening for TCP connections on localhost:port.
server-socket 0 <port> ;
: accept ( server -- client ) : accept ( server -- client )
#! Wait for a client connection. #! Wait for a client connection.
dup wait-to-accept port-handle do-accept <client-stream> ; dup wait-to-accept server-client ;