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 */
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;

63
spawn.c
View File

@ -291,41 +291,62 @@ 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++;
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);
}
unsetenv("AWESOME_RUNNING_CHILDREN");
}
/** 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;
size_t offset = 0;
size_t length = 0;
while(argv[offset] != NULL)
{
if(A_STREQ(argv[offset], "--reap"))
offset += 2;
else {
length++;
offset++;
}
}
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);
foreach(pid, running_children) {
if(buffer.len != 0)
buffer_addc(&buffer, ',');
buffer_addf(&buffer, "%d", (int) *pid);
}
if(buffer.len != 0)
setenv("AWESOME_RUNNING_CHILDREN", buffer.s, 1);
transformed[index++] = "--reap";
transformed[index++] = buffer_detach(&buffer);
buffer_wipe(&buffer);
}
transformed[index++] = NULL;
return (char * const *) transformed;
}
static gboolean
spawn_launchee_timeout(gpointer context)

View File

@ -27,7 +27,8 @@
#include <lua.h>
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 *);