Merge pull request #1809 from psychon/reap_children
Reap children even across a restart
This commit is contained in:
commit
6254e6b7d3
|
@ -115,6 +115,8 @@ 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 */
|
||||||
|
|
62
spawn.c
62
spawn.c
|
@ -62,6 +62,12 @@
|
||||||
/** 20 seconds timeout */
|
/** 20 seconds timeout */
|
||||||
#define AWESOME_SPAWN_TIMEOUT 20.0
|
#define AWESOME_SPAWN_TIMEOUT 20.0
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_pids(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return *(GPid *) a - *(GPid *)b;
|
||||||
|
}
|
||||||
|
|
||||||
/** Wrapper for unrefing startup sequence.
|
/** Wrapper for unrefing startup sequence.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -73,7 +79,11 @@ a_sn_startup_sequence_unref(SnStartupSequence **sss)
|
||||||
DO_ARRAY(SnStartupSequence *, SnStartupSequence, a_sn_startup_sequence_unref)
|
DO_ARRAY(SnStartupSequence *, SnStartupSequence, a_sn_startup_sequence_unref)
|
||||||
|
|
||||||
/** The array of startup sequence running */
|
/** The array of startup sequence running */
|
||||||
SnStartupSequence_array_t sn_waits;
|
static SnStartupSequence_array_t sn_waits;
|
||||||
|
|
||||||
|
DO_BARRAY(GPid, pid, DO_NOTHING, compare_pids)
|
||||||
|
|
||||||
|
static pid_array_t running_children;
|
||||||
|
|
||||||
/** Remove a SnStartupSequence pointer from an array and forget about it.
|
/** Remove a SnStartupSequence pointer from an array and forget about it.
|
||||||
* \param s The startup sequence to found, remove and unref.
|
* \param s The startup sequence to found, remove and unref.
|
||||||
|
@ -256,6 +266,20 @@ spawn_start_notify(client_t *c, const char * startup_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_running_child(GPid pid, gint status, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void) status;
|
||||||
|
(void) user_data;
|
||||||
|
|
||||||
|
GPid *pid_in_array = pid_array_lookup(&running_children, &pid);
|
||||||
|
if (pid_in_array != NULL) {
|
||||||
|
pid_array_remove(&running_children, pid_in_array);
|
||||||
|
} else {
|
||||||
|
warn("(Partially) unknown child %d exited?!", (int) pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Initialize program spawner.
|
/** Initialize program spawner.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -267,6 +291,40 @@ 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");
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called right before exit, serialise state in case of a restart.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
spawn_before_exit(bool restart)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if(buffer.len != 0)
|
||||||
|
setenv("AWESOME_RUNNING_CHILDREN", buffer.s, 1);
|
||||||
|
buffer_wipe(&buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -345,6 +403,7 @@ child_exit_callback(GPid pid, gint status, gpointer user_data)
|
||||||
{
|
{
|
||||||
lua_State *L = globalconf_get_lua_State();
|
lua_State *L = globalconf_get_lua_State();
|
||||||
int exit_callback = GPOINTER_TO_INT(user_data);
|
int exit_callback = GPOINTER_TO_INT(user_data);
|
||||||
|
remove_running_child(pid, status, user_data);
|
||||||
|
|
||||||
/* 'Decode' the exit status */
|
/* 'Decode' the exit status */
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
|
@ -458,6 +517,7 @@ luaA_spawn(lua_State *L)
|
||||||
int exit_callback = LUA_REFNIL;
|
int exit_callback = LUA_REFNIL;
|
||||||
/* Only do this down here to avoid leaks in case of errors */
|
/* Only do this down here to avoid leaks in case of errors */
|
||||||
luaA_registerfct(L, 6, &exit_callback);
|
luaA_registerfct(L, 6, &exit_callback);
|
||||||
|
pid_array_insert(&running_children, pid);
|
||||||
g_child_watch_add(pid, child_exit_callback, GINT_TO_POINTER(exit_callback));
|
g_child_watch_add(pid, child_exit_callback, GINT_TO_POINTER(exit_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
spawn.h
1
spawn.h
|
@ -27,6 +27,7 @@
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
|
|
||||||
void spawn_init(void);
|
void spawn_init(void);
|
||||||
|
void spawn_before_exit(bool);
|
||||||
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 *);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue