aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2020-03-29 17:49:38 +0200
committerThomas White <taw@physics.org>2020-07-29 18:42:57 +0200
commit799530870c75349fceed47b75120facb6a8345ec (patch)
treec041dd6edbdaafda8f60ebc03303361fb3fb487e
parentba77d15bc3b743dd506a943189c13c4e95f33760 (diff)
wait() on indexamajig children
-rw-r--r--src/crystfel_gui.c4
-rw-r--r--src/crystfel_gui.h4
-rw-r--r--src/gui_backend_local.c100
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;