[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
(ITS#4603) non-blocking socket breaks `ber_flush'
Full_Name: David Lukacs
Version: 2.3.24
OS: Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (194.237.142.21)
In case a backend uses sockets in non-blocking mode, and a ber message which
size is bigger than the socket buffer is to be written, `ber_flush' in
`libraries/liblber/io.c' mostly fails.
The following is a diff against `libraries/liblber/io.c' CVS version 1.111.2.2
I hope this helps someone.
--- libraries/liblber/io.c 2006-06-30 10:45:41.000000000 +0200
+++ libraries/liblber/io.c 2006-06-30 10:54:22.000000000 +0200
@@ -240,8 +240,39 @@
rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
#endif
if ( rc <= 0 ) {
- if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
- return -1;
+ if (errno == EAGAIN) {
+ fd_set sdes;
+ FD_ZERO(&sdes);
+ FD_SET(sb->sb_fd, &sdes);
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ int retval;
+ for (;;) {
+ retval = select(FD_SETSIZE, NULL, &sdes, NULL, &tv);
+ if (retval == -1) {
+ if (errno == EINTR) continue;
+ ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+ "ber_flush: select error (errno==%d, sock_desc==%d)\n",
+ errno,
+ sb->sb_fd);
+ if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
+ return -1;
+ } else if (retval == 0) {
+ ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+ "ber_flush: select timeout (%d sec)\n",
+ tv.tv_sec);
+ if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
+ return -1;
+ } else {
+ break;
+ }
+ }
+ continue;
+ } else {
+ if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
+ return -1;
+ }
}
towrite -= rc;
ber->ber_rwptr += rc;