From 2d2e73a8eec87e6caba2afd7fc85b16320b15ff3 Mon Sep 17 00:00:00 2001 From: Son Hyunjun Date: Tue, 13 Mar 2012 19:14:30 +0900 Subject: [PATCH] modify guest server --- tizen/src/emulator.c | 9 +-- tizen/src/guest_server.c | 139 ++++++++++++++++--------------- tizen/src/skin/maruskin_operation.c | 75 ++++++++--------- tizen/src/skin/maruskin_operation.h | 4 +- tizen/src/skin/maruskin_server.c | 157 ++++++++++++++++++------------------ 5 files changed, 187 insertions(+), 197 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 91bc5d2..206ac41 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -59,6 +59,7 @@ void set_emulator_condition(int state) void exit_emulator(void) { + shutdown_guest_server(); shutdown_skin_server(); SDL_Quit(); } @@ -73,7 +74,7 @@ static void construct_main_window(int skin_argc, char* skin_argv[]) } #endif -// start_guest_server(); + start_guest_server(); } @@ -141,15 +142,13 @@ int main(int argc, char* argv[]) INFO("\n"); INFO("======================================================\n"); - construct_main_window(skin_argc, skin_argv); - sdb_setup(); + construct_main_window(skin_argc, skin_argv); + INFO("qemu main start!\n"); qemu_main(qemu_argc, qemu_argv, NULL); -// shutdown_guest_server(); - exit_emulator(); return 0; diff --git a/tizen/src/guest_server.c b/tizen/src/guest_server.c index 6fd7801..cb671de 100644 --- a/tizen/src/guest_server.c +++ b/tizen/src/guest_server.c @@ -37,21 +37,16 @@ #include "skin/maruskin_server.h" #include "debug_ch.h" -MULTI_DEBUG_CHANNEL(qemu, guest_server); +MULTI_DEBUG_CHANNEL( qemu, guest_server ); -//TODO change size -#define RECV_BUF_SIZE 4 +#define RECV_BUF_SIZE 32 static void* run_guest_server( void* args ); -static int stop_svr = 0; static int svr_port = 0; static int server_sock = 0; -static int client_sock = 0; -enum { - SENSOR_DAEMON_START = 3, -}; +static int parse_val( char *buff, unsigned char data, char *parsbuf ); pthread_t start_guest_server( void ) { @@ -74,9 +69,9 @@ static void* run_guest_server( void* args ) { socklen_t client_len; port = svr_port; - if ( ( server_sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ) ) < 0 ) { - INFO( "create listen socket error: " ); - perror( "socket" ); + if ( ( server_sock = socket( PF_INET, SOCK_DGRAM, 0 ) ) < 0 ) { + ERR( "create listen socket error\n" ); + perror( "create listen socket error\n" ); goto cleanup; } memset( &server_addr, '\0', sizeof( server_addr ) ); @@ -92,100 +87,102 @@ static void* run_guest_server( void* args ) { perror( "bind" ); goto cleanup; } else { - INFO( "success to bind port[127.0.0.1:%d/tcp] for guest_server in host \n", port ); + INFO( "success to bind port[127.0.0.1:%d/udp] for guest_server in host \n", port ); } - if ( listen( server_sock, 1 ) < 0 ) { - INFO( "guest_server listen error: " ); - perror( "listen" ); - goto cleanup; - } + client_len = sizeof( client_addr ); char readbuf[RECV_BUF_SIZE]; INFO( "guest server start...port:%d\n", port ); while ( 1 ) { - if ( stop_svr ) { - break; - } - INFO( "start accepting socket...\n" ); + memset( &readbuf, 0, RECV_BUF_SIZE ); - client_len = sizeof( client_addr ); - if ( 0 > ( client_sock = accept( server_sock, (struct sockaddr*) &client_addr, &client_len ) ) ) { - ERR( "guest_servier accept error: " ); - perror( "accept" ); - continue; - } + int read_cnt = recvfrom( server_sock, readbuf, RECV_BUF_SIZE, 0, (struct sockaddr*) &client_addr, &client_len ); + + if ( 0 > read_cnt ) { + + perror( "error : guest_server read" ); + break; - while ( 1 ) { + } else { - if ( stop_svr ) { - INFO( "stop reading this socket.\n" ); + if ( 0 == read_cnt ) { + ERR( "read_cnt is 0.\n" ); break; } - memset( &readbuf, 0, RECV_BUF_SIZE ); + TRACE( "================= recv =================\n" ); + TRACE( "read_cnt:%d\n", read_cnt ); + TRACE( "readbuf:%s\n", readbuf ); - int read_cnt = read( client_sock, readbuf, RECV_BUF_SIZE ); + char command[RECV_BUF_SIZE]; + memset( command, '\0', sizeof( command ) ); - if ( 0 > read_cnt ) { - - perror( "error : guest_server read" ); - break; + parse_val( readbuf, 0x0a, command ); + TRACE( "----------------------------------------\n" ); + if ( strcmp( command, "3\n" ) == 0 ) { + TRACE( "command:%s\n", command ); + notify_sensor_daemon_start(); } else { - - if ( 0 == read_cnt ) { - INFO( "read_cnt is 0.\n" ); - break; - } - - INFO( "================= recv =================\n" ); - INFO( "read_cnt:%d\n", read_cnt ); - - //TODO parse data - char cmd = 0; - memcpy( &cmd, readbuf, sizeof( cmd ) ); - INFO( "cmd:%s\n", cmd ); - - INFO( "----------------------------------------\n" ); - switch ( cmd ) { - case SENSOR_DAEMON_START: { - notify_sensor_daemon_start(); - break; - } - default: { - ERR( "!!! unknown command : %d\n", cmd ); - break; - } - } - - INFO( "========================================\n" ); - + ERR( "!!! unknown command : %s\n", command ); } + TRACE( "========================================\n" ); } - if ( client_sock ) { - close( client_sock ); - } } - cleanup: if ( server_sock ) { + cleanup: +#ifdef __MINGW32__ + if( server_sock ) { + closesocket(server_sock); + } +#else + if ( server_sock ) { close( server_sock ); } +#endif return NULL; } +static int parse_val( char* buff, unsigned char data, char* parsbuf ) { + + int count = 0; + + while ( 1 ) { + + if ( count > 12 ) { + return -1; + } + + if ( buff[count] == data ) { + count++; + strncpy( parsbuf, buff, count ); + return count; + } + + count++; + + } + + return 0; + +} + void shutdown_guest_server( void ) { - stop_svr = 1; - if ( client_sock ) { - close( client_sock ); + INFO( "shutdown_guest_server.\n" ); +#ifdef __MINGW32__ + if( server_sock ) { + closesocket( server_sock ); } +#else if ( server_sock ) { close( server_sock ); } +#endif } diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index 293041e..34fee71 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -46,10 +46,10 @@ enum { }; enum { - DIRECTION_PORTRAIT = 0, - DIRECTION_LANDSCAPE = 1, - DIRECTION_REVERSE_PORTRAIT = 2, - DIRECTION_REVERSE_LANDSCAPE = 3, + ROTATION_PORTRAIT = 0, + ROTATION_LANDSCAPE = 1, + ROTATION_REVERSE_PORTRAIT = 2, + ROTATION_REVERSE_LANDSCAPE = 3, }; enum { @@ -70,8 +70,8 @@ enum { KEY_RELEASED = 2, }; -void start_display( int handle_id, short scale, short direction ) { - INFO( "start_display handle_id:%d, scale:%d, direction:%d\n", handle_id, scale, direction ); +void start_display( int handle_id, short scale, short rotation ) { + INFO( "start_display handle_id:%d, scale:%d, rotation:%d\n", handle_id, scale, rotation ); maruskin_sdl_init(handle_id); } @@ -131,56 +131,49 @@ void do_hardkey_event( int event_type, int keycode ) { } -void do_direction_event( int event_type) { - INFO( "do_direction_event event_type:%d", event_type); +void do_rotation_event( int event_type) { + + INFO( "do_rotation_event event_type:%d", event_type); + + int buf_size = 32; + char send_buf[32] = { 0 }; - int buf_size = 32; - char send_buf[32] = {0}; switch ( event_type ) { - case DIRECTION_PORTRAIT: - sprintf(send_buf, "1\n3\n0\n-9.80665\n0\n"); + case ROTATION_PORTRAIT: + sprintf( send_buf, "1\n3\n0\n-9.80665\n0\n" ); break; - case DIRECTION_LANDSCAPE: - sprintf(send_buf, "1\n3\n-9.80665\n0\n0\n"); + case ROTATION_LANDSCAPE: + sprintf( send_buf, "1\n3\n-9.80665\n0\n0\n" ); break; - case DIRECTION_REVERSE_PORTRAIT: - sprintf(send_buf, "1\n3\n0\n9.80665\n0\n"); + case ROTATION_REVERSE_PORTRAIT: + sprintf( send_buf, "1\n3\n0\n9.80665\n0\n" ); break; - case DIRECTION_REVERSE_LANDSCAPE: - sprintf(send_buf, "1\n3\n0\n9.80665\n0\n"); + case ROTATION_REVERSE_LANDSCAPE: + sprintf( send_buf, "1\n3\n0\n9.80665\n0\n" ); break; } // send_to_sensor_daemon - { - uint16_t s; - - s = tcp_socket_outgoing("127.0.0.1", (uint16_t)(get_sdb_base_port() + SDB_TCP_EMULD_INDEX)); - if (s < 0) { - TRACE( "can't create socket to talk to the sdb forwarding session \n"); - TRACE( "[127.0.0.1:%d/tcp] connect fail (%d:%s)\n" - , get_sdb_base_port() + SDB_TCP_EMULD_INDEX - , errno, strerror(errno)); - return; - } + int s; - socket_send(s, "sensor\n\n\n\n", 10); - socket_send(s, &buf_size, 4); - socket_send(s, send_buf, buf_size); + s = tcp_socket_outgoing( "127.0.0.1", (uint16_t) ( get_sdb_base_port() + SDB_TCP_EMULD_INDEX ) ); + if ( s < 0 ) { + ERR( "can't create socket to talk to the sdb forwarding session \n"); + ERR( "[127.0.0.1:%d/tcp] connect fail (%d:%s)\n" , get_sdb_base_port() + SDB_TCP_EMULD_INDEX , errno, strerror(errno)); + return; + } - INFO( "send(size: %d) te 127.0.0.1:%d/tcp \n", - buf_size, get_sdb_base_port() + SDB_TCP_EMULD_INDEX); + socket_send( s, "sensor\n\n\n\n", 10 ); + socket_send( s, &buf_size, 4 ); + socket_send( s, send_buf, buf_size ); + + INFO( "send to sendord(size: %d) 127.0.0.1:%d/tcp \n", buf_size, get_sdb_base_port() + SDB_TCP_EMULD_INDEX); #ifdef _WIN32 - closiesocket(s); + closiesocket( s ); #else - close(s); + close( s ); #endif - } -} -void change_lcd_state( short scale, short direction ) { - INFO( "change_lcd_state scale:%d, scale:%d\n", scale, direction ); - //TODO send request to emuld } void open_shell(void) { diff --git a/tizen/src/skin/maruskin_operation.h b/tizen/src/skin/maruskin_operation.h index dddb94f..546c4e4 100644 --- a/tizen/src/skin/maruskin_operation.h +++ b/tizen/src/skin/maruskin_operation.h @@ -38,9 +38,7 @@ void do_key_event( int event_type, int keycode ); void do_hardkey_event( int event_type, int keycode ); -void do_direction_event( int event_type ); - -void change_lcd_state( short scale, short direction ); +void do_rotation_event( int event_type ); void open_shell(void); diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index 77926af..9c6fcfb 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -41,9 +41,7 @@ #include "maruskin_operation.h" #include "debug_ch.h" -MULTI_DEBUG_CHANNEL(qemu, maruskin_server); - - +MULTI_DEBUG_CHANNEL( qemu, maruskin_server ); #define RECV_HEADER_SIZE 16 #define SEND_HEADER_SIZE 10 @@ -67,17 +65,14 @@ enum { }; enum { - SEND_HEART_BEAT = 1, - SEND_HEART_BEAT_RESPONSE = 2, - SEND_SENSOR_DAEMON_START = 800, - SEND_SHUTDOWN = 999, + SEND_HEART_BEAT = 1, SEND_HEART_BEAT_RESPONSE = 2, SEND_SENSOR_DAEMON_START = 800, SEND_SHUTDOWN = 999, }; static uint16_t svr_port = 0; static int server_sock = 0; static int client_sock = 0; -static int stop = 0; -static int sensord_initialized = 0; +static int stop_server = 0; +static int is_sensord_initialized = 0; static int stop_heartbeat = 0; static int recv_heartbeat_count = 0; @@ -90,7 +85,7 @@ static void* run_skin_server( void* args ); static int send_skin( int client_sock, short send_cmd ); static void* do_heart_beat( void* args ); static int start_heart_beat( int client_sock ); -static void stop_heart_beat(void); +static void stop_heart_beat( void ); pthread_t start_skin_server( uint16_t default_svr_port, int argc, char** argv ) { @@ -106,25 +101,33 @@ pthread_t start_skin_server( uint16_t default_svr_port, int argc, char** argv ) } -void shutdown_skin_server(void) { +void shutdown_skin_server( void ) { if ( client_sock ) { INFO( "Send shutdown to skin.\n" ); if ( 0 > send_skin( client_sock, SEND_SHUTDOWN ) ) { ERR( "fail to send SEND_SHUTDOWN to skin.\n" ); - stop = 1; + stop_server = 1; // force close +#ifdef __MINGW32__ + closesocket( client_sock ); + if ( server_sock ) { + closesocket( server_sock ); + } +#else close( client_sock ); if ( server_sock ) { close( server_sock ); } +#endif } else { // skin sent RECV_RESPONSE_SHUTDOWN. } } } -void notify_sensor_daemon_start(void) { - sensord_initialized = 1; +void notify_sensor_daemon_start( void ) { + INFO( "notify_sensor_daemon_start\n" ); + is_sensord_initialized = 1; if ( 0 > send_skin( client_sock, SEND_SENSOR_DAEMON_START ) ) { ERR( "fail to send SEND_SENSOR_DAEMON_START to skin.\n" ); } @@ -182,7 +185,7 @@ static void* run_skin_server( void* args ) { while ( 1 ) { - if ( stop ) { + if ( stop_server ) { break; } @@ -190,16 +193,16 @@ static void* run_skin_server( void* args ) { INFO( "start accepting socket...\n" ); - client_len = sizeof(client_addr); + client_len = sizeof( client_addr ); if ( 0 > ( client_sock = accept( server_sock, (struct sockaddr *) &client_addr, &client_len ) ) ) { - ERR( "skin_servier accept error: " ); - perror( "accept" ); + ERR( "skin_servier accept error\n" ); + perror( "skin_servier accept error\n" ); continue; } while ( 1 ) { - if ( stop ) { + if ( stop_server ) { INFO( "stop reading this socket.\n" ); break; } @@ -210,19 +213,20 @@ static void* run_skin_server( void* args ) { int read_cnt = read( client_sock, readbuf, RECV_HEADER_SIZE ); if ( 0 > read_cnt ) { - - perror( "error : skin_server read" ); + ERR( "skin_server read_cnt is less than 0\n" ); + perror( "skin_server read_cnt is less than 0\n" ); break; } else { if ( 0 == read_cnt ) { - INFO( "read_cnt is 0.\n" ); + ERR( "read_cnt is 0.\n" ); + perror( "read_cnt is 0.\n" ); break; } - INFO( "================= recv =================\n" ); - INFO( "read_cnt:%d\n", read_cnt ); + TRACE( "================= recv =================\n" ); + TRACE( "read_cnt:%d\n", read_cnt ); int pid = 0; long long req_id = 0; @@ -246,10 +250,10 @@ static void* run_skin_server( void* args ) { //TODO check identification with pid - INFO( "pid:%d\n", pid ); - INFO( "req_id:%lld\n", req_id ); - INFO( "cmd:%d\n", cmd ); - INFO( "length:%d\n", length ); + TRACE( "pid:%d\n", pid ); + TRACE( "req_id:%lld\n", req_id ); + TRACE( "cmd:%d\n", cmd ); + TRACE( "length:%d\n", length ); if ( 0 < length ) { @@ -257,7 +261,7 @@ static void* run_skin_server( void* args ) { int read_cnt = read( client_sock, readbuf, length ); - INFO( "data read_cnt:%d\n", read_cnt ); + TRACE( "data read_cnt:%d\n", read_cnt ); if ( 0 > read_cnt ) { perror( "error : skin_server read data" ); @@ -272,43 +276,42 @@ static void* run_skin_server( void* args ) { } - INFO( "----------------------------------------\n" ); + TRACE( "----------------------------------------\n" ); switch ( cmd ) { case RECV_START: { - INFO( "RECV_START\n" ); + TRACE( "RECV_START\n" ); if ( 0 >= length ) { - INFO( "there is no data looking at 0 length." ); + ERR( "there is no data looking at 0 length." ); continue; } int handle_id = 0; short scale = 0; - short direction = 0; + short rotation = 0; char* p = readbuf; memcpy( &handle_id, p, sizeof( handle_id ) ); p += sizeof( handle_id ); memcpy( &scale, p, sizeof( scale ) ); p += sizeof( scale ); - memcpy( &direction, p, sizeof( direction ) ); + memcpy( &rotation, p, sizeof( rotation ) ); handle_id = ntohl( handle_id ); scale = ntohs( scale ); - direction = ntohs( direction ); + rotation = ntohs( rotation ); if ( start_heart_beat( client_sock ) ) { - start_display( handle_id, scale, direction ); + start_display( handle_id, scale, rotation ); } else { - stop = 1; + stop_server = 1; } break; } case RECV_MOUSE_EVENT: { - - INFO( "RECV_MOUSE_EVENT\n" ); + TRACE( "RECV_MOUSE_EVENT\n" ); if ( 0 >= length ) { - INFO( "there is no data looking at 0 length." ); + ERR( "there is no data looking at 0 length." ); continue; } @@ -335,10 +338,9 @@ static void* run_skin_server( void* args ) { break; } case RECV_KEY_EVENT: { - - INFO( "RECV_KEY_EVENT\n" ); + TRACE( "RECV_KEY_EVENT\n" ); if ( 0 >= length ) { - INFO( "there is no data looking at 0 length." ); + ERR( "there is no data looking at 0 length." ); continue; } @@ -357,10 +359,9 @@ static void* run_skin_server( void* args ) { break; } case RECV_HARD_KEY_EVENT: { - - INFO( "RECV_HARD_KEY_EVENT\n" ); + TRACE( "RECV_HARD_KEY_EVENT\n" ); if ( 0 >= length ) { - INFO( "there is no data looking at 0 length." ); + ERR( "there is no data looking at 0 length." ); continue; } @@ -379,51 +380,49 @@ static void* run_skin_server( void* args ) { break; } case RECV_CHANGE_LCD_STATE: { - INFO( "RECV_CHANGE_LCD_STATE\n" ); + TRACE( "RECV_CHANGE_LCD_STATE\n" ); if ( 0 >= length ) { - INFO( "there is no data looking at 0 length." ); + ERR( "there is no data looking at 0 length." ); continue; } short scale = 0; - short direction = 0; + short rotation = 0; char* p = readbuf; memcpy( &scale, p, sizeof( scale ) ); p += sizeof( scale ); - memcpy( &direction, p, sizeof( direction ) ); + memcpy( &rotation, p, sizeof( rotation ) ); scale = ntohs( scale ); - direction = ntohs( direction ); - - change_lcd_state( scale, direction ); + rotation = ntohs( rotation ); - if ( sensord_initialized ) { - do_direction_event( direction ); + if ( is_sensord_initialized ) { + do_rotation_event( rotation ); } break; } case RECV_HEART_BEAT: { - INFO( "RECV_HEART_BEAT\n" ); + TRACE( "RECV_HEART_BEAT\n" ); if ( 0 > send_skin( client_sock, SEND_HEART_BEAT_RESPONSE ) ) { - INFO( "Fail to send a response of heartbeat to skin.\n" ); + ERR( "Fail to send a response of heartbeat to skin.\n" ); } break; } case RECV_RESPONSE_HEART_BEAT: { - INFO( "RECV_RESPONSE_HEART_BEAT\n" ); + TRACE( "RECV_RESPONSE_HEART_BEAT\n" ); pthread_mutex_lock( &mutex_recv_heartbeat_count ); recv_heartbeat_count = 0; pthread_mutex_unlock( &mutex_recv_heartbeat_count ); break; } case RECV_OPEN_SHELL: { - INFO( "RECV_OPEN_SHELL\n" ); + TRACE( "RECV_OPEN_SHELL\n" ); open_shell(); break; } case RECV_USB_KBD: { - INFO( "RECV_USB_KBD\n" ); + TRACE( "RECV_USB_KBD\n" ); if ( 0 >= length ) { INFO( "there is no data looking at 0 length." ); continue; @@ -434,7 +433,7 @@ static void* run_skin_server( void* args ) { char* p = readbuf; memcpy( &on, p, sizeof( on ) ); on = ntohs( on ); - if( 0 < on ) { + if ( 0 < on ) { // java boolean is 256bits '1' set. on = 1; } @@ -442,24 +441,22 @@ static void* run_skin_server( void* args ) { break; } case RECV_CLOSE: { - INFO( "RECV_CLOSE\n" ); + TRACE( "RECV_CLOSE\n" ); request_close(); - //XXX -// shutdown_skin_server(); break; } case RECV_RESPONSE_SHUTDOWN: { - INFO( "RECV_RESPONSE_SHUTDOWN\n" ); - stop = 1; + TRACE( "RECV_RESPONSE_SHUTDOWN\n" ); + stop_server = 1; break; } default: { - INFO( "!!! unknown command : %d\n", cmd ); + ERR( "!!! unknown command : %d\n", cmd ); break; } } - INFO( "========================================\n" ); + TRACE( "========================================\n" ); } @@ -467,16 +464,22 @@ static void* run_skin_server( void* args ) { stop_heart_beat(); +#ifdef __MINGW32__ + if( client_sock ) { + closesocket( client_sock ); + } +#else if ( client_sock ) { close( client_sock ); } - +#endif } cleanup: #ifdef __MINGW32__ - if(listen_s) - closesocket(listen_s); + if(server_sock) { + closesocket( server_sock ); + } #else if ( server_sock ) { close( server_sock ); @@ -535,7 +538,7 @@ static void* do_heart_beat( void* args ) { break; } - INFO( "send heartbeat to skin...\n" ); + TRACE( "send heartbeat to skin...\n" ); if ( 0 > send_skin( client_sock, SEND_HEART_BEAT ) ) { fail_count++; } else { @@ -543,7 +546,7 @@ static void* do_heart_beat( void* args ) { } if ( HEART_BEAT_FAIL_COUNT < fail_count ) { - INFO( "fail to write heart beat to skin. fail count:%d\n", HEART_BEAT_FAIL_COUNT ); + ERR( "fail to write heart beat to skin. fail count:%d\n", HEART_BEAT_FAIL_COUNT ); shutdown = 1; break; } @@ -552,11 +555,11 @@ static void* do_heart_beat( void* args ) { pthread_mutex_lock( &mutex_recv_heartbeat_count ); recv_heartbeat_count++; count = recv_heartbeat_count; - INFO( "recv_heartbeat_count:%d\n", recv_heartbeat_count ); + TRACE( "recv_heartbeat_count:%d\n", recv_heartbeat_count ); pthread_mutex_unlock( &mutex_recv_heartbeat_count ); if ( HEART_BEAT_EXPIRE_COUNT < count ) { - INFO( "received heartbeat count is expired.\n" ); + ERR( "received heartbeat count is expired.\n" ); shutdown = 1; break; } @@ -574,14 +577,14 @@ static void* do_heart_beat( void* args ) { static int start_heart_beat( int client_sock ) { if ( 0 != pthread_create( &thread_id_heartbeat, NULL, do_heart_beat, (void*) &client_sock ) ) { - INFO( "fail to create heartbean pthread.\n" ); + ERR( "fail to create heartbean pthread.\n" ); return 0; } else { return 1; } } -static void stop_heart_beat(void) { +static void stop_heart_beat( void ) { pthread_mutex_lock( &mutex_heartbeat ); stop_heartbeat = 1; pthread_cond_signal( &cond_heartbeat ); -- 2.7.4