From c5f62f02be9fd29eb3f8f7831ac98617752ea789 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 1 Apr 2021 11:38:44 +0200 Subject: GUI: Clean up old tasks when infobar is removed --- src/crystfel_gui.c | 61 +++++++++++++++++++++++++++++++++++++++++-------- src/gui_backend_local.c | 9 ++++++++ src/gui_backend_slurm.c | 9 ++++++++ src/gui_project.c | 2 +- src/gui_project.h | 6 +++-- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c index 06d4f866..07626dbb 100644 --- a/src/crystfel_gui.c +++ b/src/crystfel_gui.c @@ -175,10 +175,12 @@ const char *selected_result(struct crystfelproject *proj) * (i.e. merging) */ static int have_running_jobs(struct crystfelproject *proj) { - int i; + GSList *item = proj->tasks; - for ( i=0; in_running_tasks; i++ ) { - if ( proj->tasks[i].running ) return 1; + while ( item != NULL ) { + struct gui_task *task = item->data; + if ( task->running ) return 1; + item = item->next; } return 0; @@ -977,18 +979,49 @@ int main(int argc, char *argv[]) } +struct infobar_data +{ + struct crystfelproject *proj; + struct gui_task *task; +}; + + +static void free_ib_callback_params(gpointer cbvals, + GClosure *closure) +{ + free(cbvals); +} + + +static void remove_task(struct crystfelproject *proj, + struct gui_task *task) +{ + if ( task->running ) { + ERROR("Attempt to remove a running task!\n"); + return; + } + + if ( task->backend->free_task != NULL ) { + task->backend->free_task(task->job_priv); + } + free(task); + + proj->tasks = g_slist_remove(proj->tasks, task); +} + + static void infobar_response_sig(GtkInfoBar *infobar, gint resp, gpointer data) { - struct gui_task *task = data; + struct infobar_data *ibdata = data; if ( resp == GTK_RESPONSE_CANCEL ) { - task->backend->cancel_task(task->job_priv); + ibdata->task->backend->cancel_task(ibdata->task->job_priv); } else if ( resp == GTK_RESPONSE_CLOSE ) { gtk_widget_destroy(GTK_WIDGET(infobar)); - /* FIXME: Remove task from list */ + remove_task(ibdata->proj, ibdata->task); } else { ERROR("Unrecognised infobar response!\n"); @@ -1030,12 +1063,16 @@ void add_running_task(struct crystfelproject *proj, void *job_priv) { struct gui_task *task; + struct infobar_data *ibdata; GtkWidget *bar_area; - task = &proj->tasks[proj->n_running_tasks++]; + task = malloc(sizeof(struct gui_task)); + if ( task == NULL ) return; + task->job_priv = job_priv; task->backend = backend; task->running = 1; + proj->tasks = g_slist_append(proj->tasks, task); /* Progress info bar */ task->info_bar = gtk_info_bar_new(); @@ -1061,8 +1098,14 @@ void add_running_task(struct crystfelproject *proj, gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(task->progress_bar), TRUE); - g_signal_connect(G_OBJECT(task->info_bar), "response", - G_CALLBACK(infobar_response_sig), task); + ibdata = malloc(sizeof(struct infobar_data)); + if ( ibdata != NULL ) { + ibdata->proj = proj; + ibdata->task = task; + g_signal_connect_data(G_OBJECT(task->info_bar), "response", + G_CALLBACK(infobar_response_sig), ibdata, + free_ib_callback_params, 0); + } gtk_widget_show_all(task->info_bar); diff --git a/src/gui_backend_local.c b/src/gui_backend_local.c index 96d6c6b3..545ac776 100644 --- a/src/gui_backend_local.c +++ b/src/gui_backend_local.c @@ -79,6 +79,14 @@ struct local_job }; +static void free_task(void *job_priv) +{ + struct local_job *job = job_priv; + g_object_unref(job->workdir); + free(job->stderr_filename); +} + + static void watch_subprocess(GPid pid, gint status, gpointer vp) { struct local_job *job = vp; @@ -677,6 +685,7 @@ int make_local_backend(struct crystfel_backend *be) be->friendly_name = "Local (run on this computer)"; be->cancel_task = cancel_task; + be->free_task = free_task; be->task_status = get_task_status; be->make_indexing_parameters_widget = make_indexing_parameters_widget; diff --git a/src/gui_backend_slurm.c b/src/gui_backend_slurm.c index ed49c4c6..1da344ce 100644 --- a/src/gui_backend_slurm.c +++ b/src/gui_backend_slurm.c @@ -222,6 +222,14 @@ static int get_task_status(void *job_priv, } +static void free_task(void *job_priv) +{ + struct slurm_job *job = job_priv; + g_object_unref(job->workdir); + free(job->stderr_filename); +} + + static void cancel_task(void *job_priv) { char jobid[128]; @@ -1050,6 +1058,7 @@ int make_slurm_backend(struct crystfel_backend *be) be->friendly_name = "SLURM"; be->cancel_task = cancel_task; + be->free_task = free_task; be->task_status = get_task_status; be->make_indexing_parameters_widget = make_indexing_parameters_widget; diff --git a/src/gui_project.c b/src/gui_project.c index fba38b7c..920bc310 100644 --- a/src/gui_project.c +++ b/src/gui_project.c @@ -1093,7 +1093,7 @@ void default_project(struct crystfelproject *proj) proj->indexing_opts = NULL; proj->merging_opts = NULL; proj->ambi_opts = NULL; - proj->n_running_tasks = 0; + proj->tasks = NULL; proj->indexing_new_job_title = NULL; proj->merging_new_job_title = NULL; proj->ambi_new_job_title = NULL; diff --git a/src/gui_project.h b/src/gui_project.h index e4daeb8d..d698e720 100644 --- a/src/gui_project.h +++ b/src/gui_project.h @@ -157,6 +157,9 @@ struct crystfel_backend { /* Called to ask the backend to cancel the job */ void (*cancel_task)(void *job_priv); + /* Called to ask the backend to free any resources in the job record */ + void (*free_task)(void *job_priv); + /* Called to get the status of a task */ int (*task_status)(void *job_priv, int *running, @@ -308,8 +311,7 @@ struct crystfelproject { struct crystfel_backend *backends; int n_backends; - struct gui_task tasks[MAX_RUNNING_TASKS]; - int n_running_tasks; + GSList *tasks; struct gui_indexing_result *results; int n_results; -- cgit v1.2.3