diff options
Diffstat (limited to 'src/process_manager.c')
-rw-r--r-- | src/process_manager.c | 220 |
1 files changed, 0 insertions, 220 deletions
diff --git a/src/process_manager.c b/src/process_manager.c deleted file mode 100644 index ad3ea33..0000000 --- a/src/process_manager.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2021 Collabora Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "app_launcher.h" -#include "process_manager.h" - -struct _ProcessManager { - GObject parent_instance; - - GList *process_data; -}; - -G_DEFINE_TYPE(ProcessManager, process_manager, G_TYPE_OBJECT); - -enum { - STARTED, - TERMINATED, - N_SIGNALS -}; -static guint signals[N_SIGNALS]; - -/* - * Application info structure, used for storing relevant data - * in the `running_apps` list - */ -struct process_runtime_data { - guint watcher; - GPid pid; - const gchar *app_id; -}; - -/* - * Initialization & cleanup functions - */ - -static void process_manager_dispose(GObject *object) -{ - ProcessManager *self = APPLAUNCHD_PROCESS_MANAGER(object); - - g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self)); - - if (self->process_data) - g_list_free_full(g_steal_pointer(&self->process_data), g_free); - - G_OBJECT_CLASS(process_manager_parent_class)->dispose(object); -} - -static void process_manager_finalize(GObject *object) -{ - G_OBJECT_CLASS(process_manager_parent_class)->finalize(object); -} - -static void process_manager_class_init(ProcessManagerClass *klass) -{ - GObjectClass *object_class = (GObjectClass *)klass; - - object_class->dispose = process_manager_dispose; - object_class->finalize = process_manager_finalize; - - signals[STARTED] = g_signal_new("started", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0 , - NULL, NULL, NULL, G_TYPE_NONE, - 1, G_TYPE_STRING); - - signals[TERMINATED] = g_signal_new("terminated", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0 , - NULL, NULL, NULL, G_TYPE_NONE, - 1, G_TYPE_STRING); -} - -static void process_manager_init(ProcessManager *self) -{ -} - -/* - * Internal functions - */ - -static const gchar *get_app_id_for_pid(ProcessManager *self, GPid pid) -{ - g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), NULL); - - AppLauncher *app_launcher = app_launcher_get_default(); - guint len = g_list_length(self->process_data); - - for (guint i = 0; i < len; i++) { - struct process_runtime_data *runtime_data = - g_list_nth_data(self->process_data, i); - - if (runtime_data->pid == pid) - return runtime_data->app_id; - } - - return NULL; -} - -/* - * Internal callbacks - */ - -/* - * This function is called when a watched process terminated, so we can: - * - cleanup this application's data (and reap the process so it - * doesn't become a zombie) - * - notify listeners that the process terminated - */ -static void process_manager_app_terminated_cb(GPid pid, - gint wait_status, - gpointer data) -{ - ProcessManager *self = data; - AppLauncher *app_launcher = app_launcher_get_default(); - struct process_runtime_data *runtime_data; - const gchar *app_id; - AppInfo *app_info; - - g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self)); - - app_id = get_app_id_for_pid(self, pid); - if (!app_id) { - g_warning("Unable to retrieve app id for pid %d", pid); - return; - } - - app_info = app_launcher_get_app_info(app_launcher, app_id); - if (!app_info) { - g_warning("Unable to find running app with pid %d", pid); - return; - } - - if (g_spawn_check_exit_status(wait_status, NULL)) - g_debug("Application '%s' terminated with exit code %i", - app_id, WEXITSTATUS(wait_status)); - else - g_warning("Application '%s' crashed", app_id); - - g_spawn_close_pid(pid); - - runtime_data = app_info_get_runtime_data(app_info); - g_source_remove(runtime_data->watcher); - - app_info_set_status(app_info, APP_STATUS_INACTIVE); - app_info_set_runtime_data(app_info, NULL); - - self->process_data = g_list_remove(self->process_data, runtime_data); - g_free(runtime_data); - - g_signal_emit(self, signals[TERMINATED], 0, app_id); -} - -/* - * Public functions - */ - -ProcessManager *process_manager_new(void) -{ - return g_object_new(APPLAUNCHD_TYPE_PROCESS_MANAGER, NULL); -} - -/* - * Start an application by executing the provided command line. - */ -gboolean process_manager_start_app(ProcessManager *self, - AppInfo *app_info) -{ - g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), FALSE); - g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(app_info), FALSE); - - gboolean success; - g_autofree GStrv args = NULL; - const gchar *app_id = app_info_get_app_id(app_info); - const gchar *command = app_info_get_command(app_info); - struct process_runtime_data *runtime_data; - - runtime_data = g_new0(struct process_runtime_data, 1); - if (!runtime_data) { - g_critical("Unable to allocate runtime data structure for '%s'", - app_id); - return FALSE; - } - - runtime_data->app_id = app_id; - - args = g_strsplit(command, " ", -1); - success = g_spawn_async(NULL, args, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, - NULL, NULL, &runtime_data->pid, NULL); - if (!success) { - g_critical("Unable to start application '%s'", app_id); - g_free(runtime_data); - return FALSE; - } - - /* - * Add a watcher for the child PID in order to get notified when it dies - */ - runtime_data->watcher = g_child_watch_add(runtime_data->pid, - process_manager_app_terminated_cb, - self); - self->process_data = g_list_append(self->process_data, runtime_data); - app_info_set_runtime_data(app_info, runtime_data); - app_info_set_status(app_info, APP_STATUS_RUNNING); - - g_signal_emit(self, signals[STARTED], 0, app_id); - - return TRUE; -} |