kill: Do not kill pid 0 and embrace races

There are a number of races, and failure conditions which can lead to a
pid of 0 being returned from flatpak_instance_get_child_pid. This would
lead to a whole bunch of things getting killed.

We will skip the instance in those cases now, and retry a few times. We
also notice when the instance just goes away by itself now.

This should make killing more robust, and especially not SIGKILL pid 0.
This commit is contained in:
Sebastian Wick 2025-10-30 16:09:00 +01:00
parent 0fc61c1aff
commit 8354ee56cf

View File

@ -36,37 +36,91 @@
#include "flatpak-builtins.h"
#include "flatpak-instance.h"
#define FLATPAK_BUILTIN_KILL_N_RETRIES 5
#define FLATPAK_BUILTIN_KILL_RETRY_SLEEP_USEC (G_USEC_PER_SEC / 10)
static GOptionEntry options[] = {
{ NULL }
};
static gboolean
kill_instance (const char *id,
GError **error)
instance_equal (FlatpakInstance *a,
FlatpakInstance *b)
{
g_autoptr(GPtrArray) instances = NULL;
int j;
int killed = 0;
return g_strcmp0 (flatpak_instance_get_id (a),
flatpak_instance_get_id (b)) == 0;
}
instances = flatpak_instance_get_all ();
static GPtrArray *
kill_instances (GPtrArray *kill_list)
{
g_autoptr(GPtrArray) instances = flatpak_instance_get_all ();
g_autoptr(GPtrArray) remaining =
g_ptr_array_new_with_free_func (g_object_unref);
for (j = 0; j < instances->len; j++)
for (size_t i = 0; i < kill_list->len; i++)
{
FlatpakInstance *instance = (FlatpakInstance *) g_ptr_array_index (instances, j);
if (g_strcmp0 (id, flatpak_instance_get_app (instance)) == 0 ||
strcmp (id, flatpak_instance_get_id (instance)) == 0)
FlatpakInstance *to_kill = g_ptr_array_index (kill_list, i);
pid_t pid;
if (!g_ptr_array_find_with_equal_func (instances, to_kill,
(GEqualFunc) instance_equal,
NULL))
{
pid_t pid = flatpak_instance_get_child_pid (instance);
kill (pid, SIGKILL);
killed++;
g_info ("Instance %s disappeared", flatpak_instance_get_id (to_kill));
continue;
}
pid = flatpak_instance_get_child_pid (to_kill);
if (pid != 0)
{
kill (pid, SIGKILL);
g_info ("Instance %s killed", flatpak_instance_get_id (to_kill));
continue;
}
g_ptr_array_add (remaining, g_object_ref (to_kill));
}
g_info ("Killed %d instances", killed);
return g_steal_pointer (&remaining);
}
if (killed == 0)
static gboolean
kill_id (const char *id,
GError **error)
{
g_autoptr(GPtrArray) instances = flatpak_instance_get_all ();
g_autoptr(GPtrArray) kill_list =
g_ptr_array_new_with_free_func (g_object_unref);
for (size_t i = 0; i < instances->len; i++)
{
FlatpakInstance *instance = g_ptr_array_index (instances, i);
if (g_strcmp0 (id, flatpak_instance_get_app (instance)) != 0 &&
g_strcmp0 (id, flatpak_instance_get_id (instance)) != 0)
continue;
g_info ("Found instance %s to kill", flatpak_instance_get_id (instance));
g_ptr_array_add (kill_list, g_object_ref (instance));
}
if (kill_list->len == 0)
return flatpak_fail (error, _("%s is not running"), id);
for (size_t i = 0; i < FLATPAK_BUILTIN_KILL_N_RETRIES && kill_list->len > 0; i++)
{
g_autoptr (GPtrArray) remaining = NULL;
if (i > 0)
g_usleep (FLATPAK_BUILTIN_KILL_RETRY_SLEEP_USEC);
remaining = kill_instances (kill_list);
g_clear_pointer (&kill_list, g_ptr_array_unref);
kill_list = g_steal_pointer (&remaining);
}
return TRUE;
}
@ -77,7 +131,7 @@ flatpak_builtin_kill (int argc,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
const char *instance;
const char *id;
context = g_option_context_new (_("INSTANCE - Stop a running application"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
@ -97,9 +151,9 @@ flatpak_builtin_kill (int argc,
return FALSE;
}
instance = argv[1];
id = argv[1];
return kill_instance (instance, error);
return kill_id (id, error);
}
gboolean