summaryrefslogtreecommitdiff
path: root/src/worker.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2014-12-01 11:23:15 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2014-12-01 11:23:15 +0100
commitf234454dc08b6ba997d51d18e3129969c4e618ab (patch)
tree3de6353ce775667dc456df0d24dc17a12d37d380 /src/worker.c
parentbb88e80675820e01e17028b061eb11ae7a63d55c (diff)
downloadbiruda-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.c83
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;
}