Use command line instead of env for passing children

Commit e54361a374 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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2017-06-02 16:10:36 +02:00 committed by Daniel Hahler
parent d799eea2cf
commit af8288335b
3 changed files with 55 additions and 31 deletions

View File

@ -115,8 +115,6 @@ awesome_atexit(bool restart)
/* Disconnect *after* closing lua */ /* Disconnect *after* closing lua */
xcb_cursor_context_free(globalconf.cursor_ctx); xcb_cursor_context_free(globalconf.cursor_ctx);
xcb_disconnect(globalconf.connection); xcb_disconnect(globalconf.connection);
spawn_before_exit(restart);
} }
/** Restore the client order after a restart */ /** Restore the client order after a restart */
@ -465,7 +463,7 @@ void
awesome_restart(void) awesome_restart(void)
{ {
awesome_atexit(true); awesome_atexit(true);
execvp(awesome_argv[0], awesome_argv); execvp(awesome_argv[0], spawn_transform_commandline(awesome_argv));
fatal("execv() failed: %s", strerror(errno)); fatal("execv() failed: %s", strerror(errno));
} }
@ -529,6 +527,7 @@ main(int argc, char **argv)
{ "search", 1, NULL, 's' }, { "search", 1, NULL, 's' },
{ "no-argb", 0, NULL, 'a' }, { "no-argb", 0, NULL, 'a' },
{ "replace", 0, NULL, 'r' }, { "replace", 0, NULL, 'r' },
{ "reap", 1, NULL, '\1' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -578,6 +577,9 @@ main(int argc, char **argv)
case 'r': case 'r':
replace_wm = true; replace_wm = true;
break; break;
case '\1':
spawn_handle_reap(optarg);
break;
default: default:
exit_help(EXIT_FAILURE); exit_help(EXIT_FAILURE);
break; break;

75
spawn.c
View File

@ -291,40 +291,61 @@ spawn_init(void)
globalconf.default_screen, globalconf.default_screen,
spawn_monitor_event, spawn_monitor_event,
NULL, NULL); NULL, NULL);
}
const char* children = getenv("AWESOME_RUNNING_CHILDREN"); void
while (children != NULL) { spawn_handle_reap(const char *arg)
int pid, length; {
if (sscanf(children, "%d%n", &pid, &length) != 1) GPid pid = atoll(arg);
break; pid_array_insert(&running_children, pid);
children += length; g_child_watch_add((GPid) pid, remove_running_child, NULL);
if (*children == ',')
children++;
pid_array_insert(&running_children, pid);
g_child_watch_add((GPid) pid, remove_running_child, NULL);
}
unsetenv("AWESOME_RUNNING_CHILDREN");
} }
/** Called right before exit, serialise state in case of a restart. /** Called right before exit, serialise state in case of a restart.
*/ */
void char * const *
spawn_before_exit(bool restart) spawn_transform_commandline(char **argv)
{ {
if (!restart) size_t offset = 0;
return; size_t length = 0;
while(argv[offset] != NULL)
buffer_t buffer; {
buffer_init(&buffer); if(A_STREQ(argv[offset], "--reap"))
foreach(pid, running_children) { offset += 2;
if(buffer.len != 0) else {
buffer_addc(&buffer, ','); length++;
buffer_addf(&buffer, "%d", (int) *pid); offset++;
}
} }
if(buffer.len != 0)
setenv("AWESOME_RUNNING_CHILDREN", buffer.s, 1); length += 2*running_children.len;
buffer_wipe(&buffer);
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 static gboolean

View File

@ -27,7 +27,8 @@
#include <lua.h> #include <lua.h>
void spawn_init(void); 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 *); void spawn_start_notify(client_t *, const char *);
int luaA_spawn(lua_State *); int luaA_spawn(lua_State *);