diff --git a/src/control/control.c b/src/control/control.c index e7103dd82334..66acbf795c5e 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -203,6 +203,7 @@ void dt_control_init(const gboolean withgui) s->input_drivers = NULL; dt_atomic_set_int(&s->quitting, 0); dt_atomic_set_int(&s->pending_jobs, 0); + dt_atomic_set_int(&s->running_jobs, 0); s->cups_started = FALSE; dt_action_define_fallback(DT_ACTION_TYPE_IOP, &dt_action_def_iop); diff --git a/src/control/control.h b/src/control/control.h index d4a0c8e192f0..0447b53b06d8 100644 --- a/src/control/control.h +++ b/src/control/control.h @@ -181,6 +181,7 @@ typedef struct dt_control_t dt_atomic_int running; dt_atomic_int quitting; dt_atomic_int pending_jobs; + dt_atomic_int running_jobs; gboolean cups_started; gboolean export_scheduled; dt_pthread_mutex_t queue_mutex, cond_mutex; diff --git a/src/control/jobs.c b/src/control/jobs.c index af5212226545..24a82dfaaf61 100644 --- a/src/control/jobs.c +++ b/src/control/jobs.c @@ -516,6 +516,7 @@ static void *_control_work_res(void *ptr) dt_pthread_setname(name); free(params); const int32_t threadid_res = _control_get_threadid_res(); + dt_atomic_add_int(&s->running_jobs, 1); while(dt_control_running()) { // dt_print(DT_DEBUG_CONTROL, "[control_work] %d", threadid_res); @@ -538,6 +539,7 @@ static void *_control_worker_kicker(void *ptr) { dt_control_t *control = (dt_control_t *)ptr; dt_pthread_setname("kicker"); + dt_atomic_add_int(&control->running_jobs, 1); while(dt_control_running()) { sleep(2); @@ -561,6 +563,7 @@ static void *_control_work(void *ptr) dt_pthread_setname(name); free(params); + dt_atomic_add_int(&control->running_jobs, 1); while(dt_control_running()) { if(_control_run_job(control)) @@ -645,8 +648,40 @@ void dt_control_jobs_init() #ifdef HAVE_GPHOTO2 err |= dt_pthread_create(&control->update_gphoto_thread, dt_update_cameras_thread, control); #endif + if(err != 0) - dt_print(DT_DEBUG_ALWAYS, "[dt_control_jobs_init] couldn't create all threads, problems ahead"); + { + /* FIXME can we handle this better? + Should we unset control->running here? requires further investigation + on how to join or avoid rogue threads + */ + dt_print(DT_DEBUG_ALWAYS, "[dt_control_jobs_init] ERROR STARTING THREADS, PROBLEMS AHEAD"); + } + else // no errors reported so we test & wait + { + const int requested = control->num_threads + 1 + DT_CTL_WORKER_RESERVED; + int running = 0; + for(int i = 0; i < 1000; i++) + { + running = dt_atomic_get_int(&control->running_jobs); + dt_print(DT_DEBUG_CONTROL, "[dt_control_jobs_init] %d of %d threads running", running, requested); + if(running == requested) break; + g_usleep(1000); // let's wait for up to 1sec for OS dispatching the pthreads + } + if(running != requested) + dt_print(DT_DEBUG_ALWAYS, "[dt_control_jobs_init] ERROR STARTED %d THREADS of %d, PROBLEMS AHEAD", + running, requested); + } +} + +gboolean dt_control_all_running() +{ + if(!dt_control_running()) + return FALSE; + + dt_control_t *control = darktable.control; + const int requested = control->num_threads + 1 + DT_CTL_WORKER_RESERVED; + return dt_atomic_get_int(&control->running_jobs) == requested; } void dt_control_jobs_cleanup() diff --git a/src/control/jobs.h b/src/control/jobs.h index 2fc46ac1c23d..3e1161701c5f 100644 --- a/src/control/jobs.h +++ b/src/control/jobs.h @@ -82,6 +82,7 @@ double dt_control_job_get_progress(const dt_job_t *job); void dt_control_jobs_init(void); void dt_control_jobs_cleanup(void); int dt_control_jobs_pending(void); +gboolean dt_control_all_running(void); gboolean dt_control_add_job(dt_job_queue_t queue_id, dt_job_t *job); gboolean dt_control_add_job_res(dt_job_t *job, const int32_t res); diff --git a/src/gui/gtk.c b/src/gui/gtk.c index b860af676555..398bf0e82918 100644 --- a/src/gui/gtk.c +++ b/src/gui/gtk.c @@ -1622,7 +1622,7 @@ void dt_gui_gtk_run(dt_gui_gtk_t *gui) dt_osx_focus_window(); #endif /* start the event loop */ - if(dt_control_running()) + if(dt_control_all_running()) { g_atomic_int_set(&darktable.gui_running, 1); gtk_main();