diff options
author | Thomas White <taw@physics.org> | 2020-03-29 17:49:38 +0200 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2020-07-29 18:42:57 +0200 |
commit | 799530870c75349fceed47b75120facb6a8345ec (patch) | |
tree | c041dd6edbdaafda8f60ebc03303361fb3fb487e | |
parent | ba77d15bc3b743dd506a943189c13c4e95f33760 (diff) |
wait() on indexamajig children
-rw-r--r-- | src/crystfel_gui.c | 4 | ||||
-rw-r--r-- | src/crystfel_gui.h | 4 | ||||
-rw-r--r-- | src/gui_backend_local.c | 100 |
3 files changed, 107 insertions, 1 deletions
diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c index c086b0cf..aa548e24 100644 --- a/src/crystfel_gui.c +++ b/src/crystfel_gui.c @@ -633,6 +633,7 @@ int main(int argc, char *argv[]) proj.peak_search_params.half_pixel_shift = 1; proj.peak_search_params.revalidate = 1; proj.backend = backend_local; + proj.backend_private = NULL; proj.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(proj.window), "CrystFEL"); @@ -742,6 +743,9 @@ int main(int argc, char *argv[]) /* Send messages to report region */ set_log_message_func(add_gui_message, &proj); + /* Initialise backend */ + proj.backend->init(&proj); + gtk_window_set_default_size(GTK_WINDOW(proj.window), 1024, 768); gtk_paned_set_position(GTK_PANED(hpaned), 172); gtk_paned_set_position(GTK_PANED(vpaned), 600); diff --git a/src/crystfel_gui.h b/src/crystfel_gui.h index e303c505..ee588e73 100644 --- a/src/crystfel_gui.h +++ b/src/crystfel_gui.h @@ -59,6 +59,9 @@ struct crystfelproject; struct crystfel_backend { int (*run_unitcell)(struct crystfelproject *proj, const char *algo); + void (*cancel)(struct crystfelproject *proj); + void (*init)(struct crystfelproject *proj); + void (*shutdown)(struct crystfelproject *proj); }; @@ -99,6 +102,7 @@ struct crystfelproject { GtkWidget *progressbar; struct crystfel_backend *backend; + void *backend_private; }; #endif diff --git a/src/gui_backend_local.c b/src/gui_backend_local.c index 80057a03..00ba2037 100644 --- a/src/gui_backend_local.c +++ b/src/gui_backend_local.c @@ -28,19 +28,51 @@ #include <pty.h> #include <glib.h> +#include <sys/wait.h> #include "crystfel_gui.h" +volatile sig_atomic_t at_zombies = 0; + + +struct local_backend_priv +{ + pid_t indexamajig_pid; +}; + + +static void check_zombies(struct local_backend_priv *priv) +{ + pid_t r; + int status; + + if ( !at_zombies ) return; + + r = waitpid(priv->indexamajig_pid, &status, WNOHANG); + if ( r == -1 ) { + ERROR("waitpid() failed\n"); + } else { + STATUS("indexamajig process exited " + "with status %i\n", status); + } + priv->indexamajig_pid = 0; + at_zombies = 0; +} + + static gboolean index_readable(GIOChannel *source, GIOCondition cond, void *vp) { GIOStatus r; GError *err = NULL; struct crystfelproject *proj = vp; + struct local_backend_priv *priv = proj->backend_private; gchar *line; double frac = 0.1; + check_zombies(priv); + r = g_io_channel_read_line(source, &line, NULL, NULL, &err); if ( r == G_IO_STATUS_EOF ) { STATUS("End of output.\n"); @@ -108,8 +140,12 @@ static int run_unitcell(struct crystfelproject *proj, char index_str[64]; char peaks_str[64]; int n_args; + struct local_backend_priv *priv = proj->backend_private; - STATUS("run unit cell with '%s'!\n", algo); + if ( at_zombies ) { + STATUS("Try again in a moment!\n"); + return 1; + } if ( write_file_list(proj) ) { STATUS("Failed to write list\n"); @@ -188,6 +224,7 @@ static int run_unitcell(struct crystfelproject *proj, } + priv->indexamajig_pid = pid; ioch = g_io_channel_unix_new(pty); g_io_add_watch(ioch, G_IO_IN | G_IO_ERR | G_IO_HUP, index_readable, proj); @@ -198,9 +235,70 @@ static int run_unitcell(struct crystfelproject *proj, } +static void cancel(struct crystfelproject *proj) +{ + struct local_backend_priv *priv = proj->backend_private; + + if ( priv->indexamajig_pid == 0 ) { + ERROR("Indexamajig not running!\n"); + return; + } + + ERROR("Cancelling!!!\n"); +} + + +static void shutdown_backend(struct crystfelproject *proj) +{ + struct local_backend_priv *priv = proj->backend_private; + free(priv); +} + + +static void sigchld_handler(int sig, siginfo_t *si, void *uc_v) +{ + at_zombies = 1; +} + + +static void init_backend(struct crystfelproject *proj) +{ + struct local_backend_priv *priv; + struct sigaction sa; + int r; + + priv = malloc(sizeof(struct local_backend_priv)); + if ( priv == NULL ) { + ERROR("Failed to initialise backend\n"); + return; + } + + priv->indexamajig_pid = 0; + + /* Signal handler */ + sa.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_RESTART; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = sigchld_handler; + r = sigaction(SIGCHLD, &sa, NULL); + if ( r == -1 ) { + ERROR("Failed to set signal handler!\n"); + return; + } + + /* Callback to check on signals */ + g_timeout_add_seconds(1, G_SOURCE_FUNC(check_zombies), priv); + + proj->backend_private = priv; + STATUS("Local backend initialised.\n"); +} + + struct crystfel_backend _backend_local = { + .init = init_backend, + .shutdown = shutdown_backend, .run_unitcell = run_unitcell, + .cancel = cancel, }; struct crystfel_backend *backend_local = &_backend_local; |