The following commit has been merged in the master branch:
commit 9226ff433d1a56cb40894638d3c21252b3b7a0e6
Author: Marek Lindner <lindner_marek(a)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;
--
batman; test conversation