From af8288335b6431581f3c9295e1aa7b41b2892062 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 2 Jun 2017 16:10:36 +0200 Subject: [PATCH] Use command line instead of env for passing children Commit e54361a374d07743326 added code so that we pass the list of currently running children across restart via an environment variable. As Colin Walters correctly points out, setenv() is not safe in a multi-threaded processes. Thus, instead of using the environment, use the command line to pass this information along. https://github.com/awesomeWM/awesome/issues/1812 Signed-off-by: Uli Schlachter --- awesome.c | 8 +++--- spawn.c | 75 +++++++++++++++++++++++++++++++++++-------------------- spawn.h | 3 ++- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/awesome.c b/awesome.c index 4235af193..e780e72c0 100644 --- a/awesome.c +++ b/awesome.c @@ -115,8 +115,6 @@ awesome_atexit(bool restart) /* Disconnect *after* closing lua */ xcb_cursor_context_free(globalconf.cursor_ctx); xcb_disconnect(globalconf.connection); - - spawn_before_exit(restart); } /** Restore the client order after a restart */ @@ -465,7 +463,7 @@ void awesome_restart(void) { awesome_atexit(true); - execvp(awesome_argv[0], awesome_argv); + execvp(awesome_argv[0], spawn_transform_commandline(awesome_argv)); fatal("execv() failed: %s", strerror(errno)); } @@ -529,6 +527,7 @@ main(int argc, char **argv) { "search", 1, NULL, 's' }, { "no-argb", 0, NULL, 'a' }, { "replace", 0, NULL, 'r' }, + { "reap", 1, NULL, '\1' }, { NULL, 0, NULL, 0 } }; @@ -578,6 +577,9 @@ main(int argc, char **argv) case 'r': replace_wm = true; break; + case '\1': + spawn_handle_reap(optarg); + break; default: exit_help(EXIT_FAILURE); break; diff --git a/spawn.c b/spawn.c index 0f1e6db19..e152559b9 100644 --- a/spawn.c +++ b/spawn.c @@ -291,40 +291,61 @@ spawn_init(void) globalconf.default_screen, spawn_monitor_event, NULL, NULL); +} - const char* children = getenv("AWESOME_RUNNING_CHILDREN"); - while (children != NULL) { - int pid, length; - if (sscanf(children, "%d%n", &pid, &length) != 1) - break; - children += length; - if (*children == ',') - children++; - - pid_array_insert(&running_children, pid); - g_child_watch_add((GPid) pid, remove_running_child, NULL); - } - unsetenv("AWESOME_RUNNING_CHILDREN"); +void +spawn_handle_reap(const char *arg) +{ + GPid pid = atoll(arg); + pid_array_insert(&running_children, pid); + g_child_watch_add((GPid) pid, remove_running_child, NULL); } /** Called right before exit, serialise state in case of a restart. */ -void -spawn_before_exit(bool restart) +char * const * +spawn_transform_commandline(char **argv) { - if (!restart) - return; - - buffer_t buffer; - buffer_init(&buffer); - foreach(pid, running_children) { - if(buffer.len != 0) - buffer_addc(&buffer, ','); - buffer_addf(&buffer, "%d", (int) *pid); + size_t offset = 0; + size_t length = 0; + while(argv[offset] != NULL) + { + if(A_STREQ(argv[offset], "--reap")) + offset += 2; + else { + length++; + offset++; + } } - if(buffer.len != 0) - setenv("AWESOME_RUNNING_CHILDREN", buffer.s, 1); - buffer_wipe(&buffer); + + length += 2*running_children.len; + + const char ** transformed = p_new(const char *, length+1); + size_t index = 0; + offset = 0; + while(argv[index + offset] != NULL) + { + if(A_STREQ(argv[index + offset], "--reap")) + offset += 2; + else { + transformed[index] = argv[index + offset]; + index++; + } + } + + foreach(pid, running_children) + { + buffer_t buffer; + buffer_init(&buffer); + buffer_addf(&buffer, "%d", (int) *pid); + + transformed[index++] = "--reap"; + transformed[index++] = buffer_detach(&buffer); + buffer_wipe(&buffer); + } + transformed[index++] = NULL; + + return (char * const *) transformed; } static gboolean diff --git a/spawn.h b/spawn.h index 5b165fce2..0949cce6c 100644 --- a/spawn.h +++ b/spawn.h @@ -27,7 +27,8 @@ #include void spawn_init(void); -void spawn_before_exit(bool); +void spawn_handle_reap(const char *); +char * const * spawn_transform_commandline(char **); void spawn_start_notify(client_t *, const char *); int luaA_spawn(lua_State *);