9898#endif
9999# include <errno.h>
100100# include <unistd.h>
101+ # include <poll.h>
102+ # define USE_POLL 1
101103
102104#endif /* !ACORN */
103105
@@ -177,7 +179,10 @@ typedef struct privateSocketStruct
177179 socklen_t senderSize ; /* dynamic sizeof(sender) */
178180 int multiListen ; /* whether to listen for multiple connections */
179181 int acceptedSock ; /* a connection that has been accepted */
180- int notifiedOfWritability ; /* flag compensates for select denying writable */
182+ int notifiedOfWritability ;/* flag avoids calling select/poll a second time */
183+ #define notifiedOfWritability (pss ) ((pss)->notifiedOfWritability)
184+ #define setNoticeOfWritability (pss ) ((pss)->notifiedOfWritability = 1)
185+ #define clearNoticeOfWritability (pss ) ((pss)->notifiedOfWritability = 0)
181186} privateSocketStruct ;
182187
183188#define CONN_NOTIFY (1<<0)
@@ -344,19 +349,34 @@ socketReadable(int s)
344349static int
345350socketWritable (int s )
346351{
352+ #if USE_POLL
353+ struct pollfd fd ;
354+
355+ fd .fd = s ;
356+ fd .events = POLLOUT ;
357+
358+ # ifdef AIO_DEBUG
359+ if (poll (& fd , 1 , 0 ) < 0 )
360+ perror ("socketWritable: poll(&fd, 1, 0)" );
361+ # else
362+ poll (& fd , 1 , 0 );
363+ # endif
364+ return fd .revents & POLLOUT ;
365+ #else
347366 struct timeval tv = { 0 , 0 }; // i.e. poll
348367 fd_set fds ;
349368
350369 FD_ZERO (& fds );
351370 FD_SET (s , & fds );
352- #ifdef AIO_DEBUG
371+ # ifdef AIO_DEBUG
353372 { int r = select (s + 1 , 0 , & fds , 0 , & tv );
354373 if (r < 0 )
355374 perror ("socketWritable: select(1,0,&fd,0,&poll)" );
356375 return r > 0 ;
357376 }
358- #else
377+ # else
359378 return select (s + 1 , 0 , & fds , 0 , & tv ) > 0 ;
379+ # endif
360380#endif
361381}
362382
@@ -503,7 +523,7 @@ dataHandler(int fd, void *data, int flags)
503523 * in sqSocketSendDone answering false for new sockets. So we subvert select
504524 * by setting the notifiedOfWritability flag, tested in sqSocketSendDone.
505525 */
506- pss -> notifiedOfWritability = true ;
526+ setNoticeOfWritability ( pss ) ;
507527 }
508528 if (flags & AIO_X )
509529 {
@@ -1148,9 +1168,8 @@ sqSocketSendDone(SocketPtr s)
11481168 * in sqSocketSendDone answering false for new sockets. So we subvert select
11491169 * by testing the notifiedOfWritability flag, set in dataHandler.
11501170 */
1151- if (PSP (s )-> notifiedOfWritability )
1152- return true;
1153- if (socketWritable (SOCKET (s )))
1171+ if (notifiedOfWritability (PSP (s ))
1172+ || socketWritable (SOCKET (s )))
11541173 return true;
11551174 FPRINTF ((stderr , "sqSocketSendDone(%d) !socketWritable\n" , SOCKET (s )));
11561175 aioHandle (SOCKET (s ), dataHandler , AIO_WX );
@@ -1220,22 +1239,37 @@ sqSocketReceiveDataBufCount(SocketPtr s, char *buf, sqInt bufSize)
12201239sqInt
12211240sqSocketSendDataBufCount (SocketPtr s , char * buf , sqInt bufSize )
12221241{
1223- int nsent = 0 ;
1242+ int nsent , err = 0 ;
12241243
12251244 if (!socketValid (s ))
12261245 return -1 ;
12271246
1228- PSP (s )-> notifiedOfWritability = false ;
1247+ clearNoticeOfWritability ( PSP (s )) ;
12291248 if (TCPSocketType != s -> socketType )
12301249 {
12311250 /* --- UDP/RAW --- */
12321251 FPRINTF ((stderr , "UDP sendData(%d, %ld)\n" , SOCKET (s ), bufSize ));
12331252 if ((nsent = sendto (SOCKET (s ), buf , bufSize , 0 , (struct sockaddr * )& SOCKETPEER (s ), sizeof (SOCKETPEER (s )))) <= 0 )
12341253 {
1235- int err = errno ;
1236- if (err == EWOULDBLOCK ) /* asynchronous write in progress */
1254+ if ( nsent < 0
1255+ && (err = errno ) == EWOULDBLOCK ) /* asynchronous write in progress */
12371256 return 0 ;
1238- FPRINTF ((stderr , "UDP send failed %d %s\n" , err , strerror (err )));
1257+ FPRINTF ((stderr , "UDP sendto failed %d %s\n" , err , strerror (err )));
1258+ /* IEEE Std 1003.1, 2004 Edition, sendto - send a message on a socket
1259+ * [EISCONN] A destination address was specified and the socket
1260+ * is already connected. This error may or may not be
1261+ * returned for connection mode sockets.
1262+ * Hence use send if socket is connected.
1263+ */
1264+ if (nsent < 0 && err == EISCONN ) {
1265+ FPRINTF ((stderr , "UDP retry sendData(%d, %ld)\n" , SOCKET (s ), bufSize ));
1266+ if ((nsent = send (SOCKET (s ), buf , bufSize , 0 )) > 0 )
1267+ goto completed ;
1268+ if (nsent < 0
1269+ && (err = errno ) == EWOULDBLOCK ) /* asynchronous write in progress */
1270+ return 0 ;
1271+ FPRINTF ((stderr , "UDP send failed %d %s\n" , err , strerror (err )));
1272+ }
12391273 SOCKETERROR (s )= err ;
12401274 return 0 ;
12411275 }
@@ -1246,22 +1280,21 @@ sqSocketSendDataBufCount(SocketPtr s, char *buf, sqInt bufSize)
12461280 FPRINTF ((stderr , "TCP sendData(%d, %ld)\n" , SOCKET (s ), bufSize ));
12471281 if ((nsent = write (SOCKET (s ), buf , bufSize )) <= 0 )
12481282 {
1249- if ((nsent == -1 ) && (errno == EWOULDBLOCK ))
1283+ err = nsent < 0 ? errno : 0 ;
1284+ if (err == EWOULDBLOCK )
12501285 {
12511286 FPRINTF ((stderr , "TCP sendData(%d, %ld) -> %d [blocked]" ,
12521287 SOCKET (s ), bufSize , nsent ));
12531288 return 0 ;
12541289 }
1255- else
1256- {
1257- /* error: most likely "connection closed by peer" */
1258- SOCKETSTATE (s )= OtherEndClosed ;
1259- SOCKETERROR (s )= errno ;
1260- FPRINTF ((stderr , "TCP write failed -> %d" , SOCKETERROR (s )));
1261- return 0 ;
1262- }
1290+ /* error: most likely "connection closed by peer" */
1291+ SOCKETSTATE (s )= OtherEndClosed ;
1292+ SOCKETERROR (s )= err ;
1293+ FPRINTF ((stderr , "TCP write failed -> %d" , SOCKETERROR (s )));
1294+ return 0 ;
12631295 }
12641296 }
1297+ completed :
12651298 /* write completed synchronously */
12661299 FPRINTF ((stderr , "sendData(%d) done = %d\n" , SOCKET (s ), nsent ));
12671300 return nsent ;
@@ -1315,7 +1348,7 @@ sqSockettoHostportSendDataBufCount(SocketPtr s, sqInt address, sqInt port, char
13151348 saddr .sin_family = AF_INET ;
13161349 saddr .sin_port = htons ((short )port );
13171350 saddr .sin_addr .s_addr = htonl (address );
1318- PSP (s )-> notifiedOfWritability = false ;
1351+ clearNoticeOfWritability ( PSP (s )) ;
13191352 {
13201353 int nsent = sendto (SOCKET (s ), buf , bufSize , 0 , (struct sockaddr * )& saddr , sizeof (saddr ));
13211354 if (nsent >= 0 )
@@ -2376,7 +2409,7 @@ sqSocketSendUDPToSizeDataBufCount(SocketPtr s, char *addr, sqInt addrSize, char
23762409 if (socketValid (s ) && addressValid (addr , addrSize ) && (TCPSocketType != s -> socketType )) /* --- UDP/RAW --- */
23772410 {
23782411 int nsent = sendto (SOCKET (s ), buf , bufSize , 0 , socketAddress (addr ), addrSize - AddressHeaderSize );
2379- PSP (s )-> notifiedOfWritability = false ;
2412+ clearNoticeOfWritability ( PSP (s )) ;
23802413 if (nsent >= 0 )
23812414 return nsent ;
23822415
0 commit comments