proxy: Deal with close() failures (and EINTR errnos) comprehensively

This commit is contained in:
nick
2013-03-15 12:07:16 +00:00
parent f89352aa28
commit 21ac3cd0ed
4 changed files with 42 additions and 11 deletions

View File

@@ -90,8 +90,9 @@ int proxy_connect_to_upstream( struct proxier* proxy )
} }
if( !socket_nbd_read_hello( fd, &size ) ) { if( !socket_nbd_read_hello( fd, &size ) ) {
FATAL_IF_NEGATIVE( WARN_IF_NEGATIVE(
close( fd ), SHOW_ERRNO( "FIXME: shouldn't be fatal" ) sock_try_close( fd ),
"Couldn't close() after failed read of NBD hello on fd %i", fd
); );
return 0; return 0;
} }
@@ -114,10 +115,10 @@ void proxy_disconnect_from_upstream( struct proxier* proxy )
debug(" Closing upstream connection" ); debug(" Closing upstream connection" );
/* TODO: An NBD disconnect would be pleasant here */ /* TODO: An NBD disconnect would be pleasant here */
WARN_IF_NEGATIVE(
FATAL_IF_NEGATIVE( sock_try_close( proxy->upstream_fd ),
close( proxy->upstream_fd ), "Failed to close() fd %i when disconnecting from upstream",
SHOW_ERRNO( "FIXME: shouldn't be fatal" ) proxy->upstream_fd
); );
proxy->upstream_fd = -1; proxy->upstream_fd = -1;
} }
@@ -442,10 +443,11 @@ int proxy_accept( struct proxier* params )
params->downstream_fd = client_fd; params->downstream_fd = client_fd;
proxy_session( params ); proxy_session( params );
if ( close( params->downstream_fd ) == -1 ) { WARN_IF_NEGATIVE(
warn( SHOW_ERRNO( "FIXME: close returned" ) ); sock_try_close( params->downstream_fd ),
} "Couldn't close() downstram fd %i after proxy session",
params->downstream_fd
);
params->downstream_fd = -1; params->downstream_fd = -1;
} }
@@ -467,7 +469,10 @@ void proxy_cleanup( struct proxier* params )
info( "cleaning up" ); info( "cleaning up" );
if ( -1 != params->listen_fd ) { if ( -1 != params->listen_fd ) {
close( params->listen_fd ); WARN_IF_NEGATIVE(
sock_try_close( params->listen_fd ),
"Failed to close() listen_fd %i", params->listen_fd
);
} }
debug( "Cleanup done" ); debug( "Cleanup done" );

View File

@@ -216,3 +216,24 @@ out:
return result; return result;
} }
int sock_try_close( int fd )
{
int result;
do {
result = close( fd );
if ( result == -1 ) {
if ( EINTR == errno ) {
continue; /* retry EINTR */
} else {
warn( SHOW_ERRNO( "Failed to close() fd %i", fd ) );
break; /* Other errors get reported */
}
}
} while( 0 );
return result;
}

View File

@@ -34,5 +34,8 @@ int sock_try_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptf
/* Try to call connect(), timing out after wait seconds */ /* Try to call connect(), timing out after wait seconds */
int sock_try_connect( int fd, struct sockaddr* to, socklen_t addrlen, int wait ); int sock_try_connect( int fd, struct sockaddr* to, socklen_t addrlen, int wait );
/* Try to call close(), retrying EINTR */
int sock_try_close( int fd );
#endif #endif

View File

@@ -150,5 +150,7 @@ void mylog(int line_level, const char* format, ...);
#define SHOW_ERRNO( msg, ... ) msg ": %s (%i)", ##__VA_ARGS__, ( errno == 0 ? "EOF" : strerror(errno) ), errno #define SHOW_ERRNO( msg, ... ) msg ": %s (%i)", ##__VA_ARGS__, ( errno == 0 ? "EOF" : strerror(errno) ), errno
#define WARN_IF_NEGATIVE( value, msg, ... ) if ( value < 0 ) { warn( msg, ##__VA_ARGS__ ); }
#endif #endif