diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2014-12-01 11:23:15 +0100 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2014-12-01 11:23:15 +0100 |
commit | f234454dc08b6ba997d51d18e3129969c4e618ab (patch) | |
tree | 3de6353ce775667dc456df0d24dc17a12d37d380 /src/worker.c | |
parent | bb88e80675820e01e17028b061eb11ae7a63d55c (diff) | |
download | biruda-f234454dc08b6ba997d51d18e3129969c4e618ab.tar.gz biruda-f234454dc08b6ba997d51d18e3129969c4e618ab.tar.bz2 |
using a dedicated orker thread to drive the glib main loop, detecting
termination of the process now correctly
Diffstat (limited to 'src/worker.c')
-rw-r--r-- | src/worker.c | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/src/worker.c b/src/worker.c index 6cfa1bb..a7554a4 100644 --- a/src/worker.c +++ b/src/worker.c @@ -58,52 +58,74 @@ typedef struct { GPid pid; gint out, err; worker_t *worker; + pthread_t thread; + GMainLoop *main_loop; } direct_glib_execution_worker_data_t; static void watch_child( GPid pid, gint status, gpointer *data ) { - printf( "ENDENDEND %d\n", pid ); + direct_glib_execution_worker_data_t *wed = (direct_glib_execution_worker_data_t *)data; + + printf( "Worker child with PID %d terminated.\n", wed->pid ); + g_spawn_close_pid( pid ); + + g_main_loop_quit( wed->main_loop ); } - -int worker_init( worker_t *worker ) + +static void *worker_func( void *thread_data ) { - if( worker->state == WORKER_STATE_RUNNING ) { - return 0; - } - + direct_glib_execution_worker_data_t *wed = (direct_glib_execution_worker_data_t *)thread_data; + worker_t *worker = wed->worker; + gchar *argv[] = { worker->command, NULL }; - worker->execution_data = malloc( sizeof( direct_glib_execution_worker_data_t ) ); - direct_glib_execution_worker_data_t *wed = - (direct_glib_execution_worker_data_t *)worker->execution_data; - wed->worker = worker; gboolean ret = g_spawn_async_with_pipes( NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &wed->pid, NULL, &wed->out, &wed->err, NULL ); if( !ret ) { g_error( "Starting worker failed" ); - return -1; + return NULL; } GMainContext *context = g_main_context_default( ); - GMainLoop *main_loop = g_main_loop_new( context, TRUE ); + wed->main_loop = g_main_loop_new( context, TRUE ); g_child_watch_add( wed->pid, (GChildWatchFunc)watch_child, (gpointer *)wed ); - // TODO: first one blocks (of course).. - //~ g_main_loop_run( main_loop ); + worker->state = WORKER_STATE_RUNNING; + + g_main_loop_run( wed->main_loop ); + + worker->state = WORKER_STATE_STOPPED; + + return NULL; +} + +int worker_init( worker_t *worker ) +{ + if( worker->state == WORKER_STATE_RUNNING ) { + return 0; + } + + pthread_attr_t attr; + int res; - // .. second one should go into the coordinator loop - // (and should not leak the glib-based implementation - // to the coordinator) - //~ for( ;; ) { - //~ gboolean res = g_main_context_iteration( context, FALSE ); - //~ sleep( 1 ); - //~ } + res = pthread_attr_init( &attr ); + if( res != 0 ) { + return 1; + } + + worker->execution_data = malloc( sizeof( direct_glib_execution_worker_data_t ) ); + direct_glib_execution_worker_data_t *wed = + (direct_glib_execution_worker_data_t *)worker->execution_data; + wed->worker = worker; - worker->state = WORKER_STATE_RUNNING; - + res = pthread_create( &wed->thread, &attr, worker_func, (void *)wed ); + if( res != 0 ) { + return 1; + } + return 0; } @@ -121,7 +143,16 @@ void worker_terminate( worker_t *worker ) worker->execution_data = NULL; } -int worker_free( ) +int worker_free( worker_t *worker ) { - return 0; + direct_glib_execution_worker_data_t *wed = (direct_glib_execution_worker_data_t *)worker->execution_data; + void *result; + int res; + + res = pthread_join( wed->thread, &result ); + if( res != 0 ) { + return 1; + } + + return 0; } |