The following commit has been merged in the master branch: commit 9226ff433d1a56cb40894638d3c21252b3b7a0e6 Author: Marek Lindner lindner_marek@yahoo.de Date: Sat Apr 7 19:19:26 2007 +0200
add mutex to avoid tcp timeout deadlock (nothing beautiful)
diff --git a/batman.c b/batman.c index 63a43f0..6922d52 100644 --- a/batman.c +++ b/batman.c @@ -29,6 +29,7 @@ #include "originator.h" #include "schedule.h"
+#include <errno.h> /* should be removed together with tcp control channel */
/* "-d" is the command line switch for the debug level, @@ -90,6 +91,7 @@ uint32_t bidirectional_timeout = 0; /* bidirectional neighbour reply timeout i
struct gw_node *curr_gateway = NULL; pthread_t curr_gateway_thread_id = 0; +pthread_mutex_t curr_gw_mutex = PTHREAD_MUTEX_INITIALIZER;
uint32_t pref_gateway = 0;
@@ -301,23 +303,34 @@ void choose_gw() {
if ( curr_gateway != tmp_curr_gw ) {
- if ( curr_gateway != NULL ) { + if ( pthread_mutex_trylock( &curr_gw_mutex ) == 0 ) {
- debug_output( 3, "Removing default route - better gateway found\n" ); + if ( curr_gateway != NULL ) {
- del_default_route(); + debug_output( 3, "Removing default route - better gateway found\n" );
- } + del_default_route(); + + }
- curr_gateway = tmp_curr_gw; + curr_gateway = tmp_curr_gw; + + /* may be the last gateway is now gone */ + if ( ( curr_gateway != NULL ) && ( !is_aborted() ) ) { + + addr_to_string( curr_gateway->orig_node->orig, orig_str, ADDR_STR_LEN ); + debug_output( 3, "Adding default route to %s (%i,%i,%i)\n", orig_str, max_gw_class, max_packets, max_gw_factor ); + + add_default_route(); + + }
- /* may be the last gateway is now gone */ - if ( ( curr_gateway != NULL ) && ( !is_aborted() ) ) { + if ( pthread_mutex_unlock( &curr_gw_mutex ) < 0 ) + debug_output( 0, "Error - could not unlock mutex (choose_gw): %s \n", strerror( errno ) );
- addr_to_string( curr_gateway->orig_node->orig, orig_str, ADDR_STR_LEN ); - debug_output( 3, "Adding default route to %s (%i,%i,%i)\n", orig_str, max_gw_class, max_packets, max_gw_factor ); + } else {
- add_default_route(); + debug_output( 0, "Warning - could not change default route (mutex locked): %s \n", strerror( EBUSY ) );
}
diff --git a/batman.h b/batman.h index a1d1544..35d6605 100644 --- a/batman.h +++ b/batman.h @@ -76,7 +76,8 @@ extern uint32_t pref_gateway; extern unsigned char *hna_buff;
extern struct gw_node *curr_gateway; -pthread_t curr_gateway_thread_id; +extern pthread_t curr_gateway_thread_id; +extern pthread_mutex_t curr_gw_mutex;
extern uint8_t found_ifs; extern int32_t receive_max_sock; diff --git a/posix-specific.c b/posix-specific.c index a5ce1a9..c3f5a2a 100644 --- a/posix-specific.c +++ b/posix-specific.c @@ -1041,13 +1041,33 @@ void *client_to_gw_tun( void *arg ) {
}
- if ( connect ( curr_gateway_tcp_sock, (struct sockaddr *)&gw_addr, sizeof(struct sockaddr) ) < 0 ) { + if ( pthread_mutex_lock( &curr_gw_mutex ) == 0 ) {
- debug_output( 0, "Error - can't connect to gateway: %s\n", strerror(errno) ); - close( curr_gateway_tcp_sock ); + if ( connect ( curr_gateway_tcp_sock, (struct sockaddr *)&gw_addr, sizeof(struct sockaddr) ) < 0 ) { + + debug_output( 0, "Error - can't connect to gateway: %s\n", strerror(errno) ); + close( curr_gateway_tcp_sock ); + + curr_gw_data->gw_node->last_failure = get_time(); + curr_gw_data->gw_node->unavail_factor++; + + curr_gateway = NULL; + debugFree( arg, 1207 ); + + if ( pthread_mutex_unlock( &curr_gw_mutex ) != 0 ) + debug_output( 0, "Error - could not unlock mutex (client_to_gw_tun => 1): %s \n", strerror( errno ) ); + + return NULL;
- curr_gw_data->gw_node->last_failure = get_time(); - curr_gw_data->gw_node->unavail_factor++; + } + + if ( pthread_mutex_unlock( &curr_gw_mutex ) != 0 ) + debug_output( 0, "Error - could not unlock mutex (client_to_gw_tun => 2): %s \n", strerror( errno ) ); + + } else { + + debug_output( 0, "Error - could not lock mutex (client_to_gw_tun => 1): %s \n", strerror( errno ) ); + close( curr_gateway_tcp_sock );
curr_gateway = NULL; debugFree( arg, 1207 ); @@ -1114,12 +1134,28 @@ void *client_to_gw_tun( void *arg ) {
server_keep_alive_timeout = get_time();
- if ( write( curr_gateway_tcp_sock, keep_alive_string, sizeof( keep_alive_string ) ) < 0 ) { + if ( pthread_mutex_lock( &curr_gw_mutex ) == 0 ) {
- debug_output( 3, "server_keepalive failed: %s\n", strerror(errno) ); + if ( write( curr_gateway_tcp_sock, keep_alive_string, sizeof( keep_alive_string ) ) < 0 ) { + + debug_output( 3, "server_keepalive failed: %s\n", strerror(errno) ); + + curr_gw_data->gw_node->last_failure = get_time(); + curr_gw_data->gw_node->unavail_factor++; + + if ( pthread_mutex_unlock( &curr_gw_mutex ) != 0 ) + debug_output( 0, "Error - could not unlock mutex (client_to_gw_tun => 3): %s \n", strerror( errno ) ); + + break; + + } + + if ( pthread_mutex_unlock( &curr_gw_mutex ) != 0 ) + debug_output( 0, "Error - could not unlock mutex (client_to_gw_tun => 4): %s \n", strerror( errno ) ); + + } else {
- curr_gw_data->gw_node->last_failure = get_time(); - curr_gw_data->gw_node->unavail_factor++; + debug_output( 0, "Error - could not lock mutex (client_to_gw_tun => 2): %s \n", strerror( errno ) );
break;