--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#ifndef __LAUNCHPAD_WORKER_H__
+#define __LAUNCHPAD_WORKER_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef bool (*worker_job_cb)(void *user_data);
+
+int _worker_add_job(worker_job_cb callback, void *user_data);
+
+int _worker_init(void);
+
+void _worker_fini(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LAUNCHPAD_WORKER_H__ */
#include "launchpad_proc.h"
#include "launchpad_signal.h"
#include "launchpad_types.h"
+#include "launchpad_worker.h"
#include "loader_info.h"
#include "perf.h"
bool exists;
};
+struct cleanup_info_s {
+ char *appid;
+ int pid;
+};
+
static int __sys_hwacc;
static GList *loader_info_list;
static GList *app_defined_loader_info_list;
return true;
}
+static void __destroy_cleanup_info(struct cleanup_info_s *info)
+{
+ if (!info)
+ return;
+
+ free(info->appid);
+ free(info);
+}
+
+static struct cleanup_info_s *__create_cleanup_info(const char *appid, int pid)
+{
+ struct cleanup_info_s *info;
+
+ info = malloc(sizeof(struct cleanup_info_s));
+ if (!info) {
+ _E("Out of memory");
+ return NULL;
+ }
+
+ info->appid = strdup(appid);
+ if (!info->appid) {
+ _E("strdup(%s) is failed", appid);
+ __destroy_cleanup_info(info);
+ return NULL;
+ }
+
+ info->pid = pid;
+
+ return info;
+}
+
+static bool __cleanup_app_cb(void *user_data)
+{
+ struct cleanup_info_s *info = (struct cleanup_info_s *)user_data;
+
+ _W("security_manager_cleanup_app() ++");
+ security_manager_cleanup_app(info->appid, getuid(), info->pid);
+ _W("security_manager_cleanup_app() --");
+ __destroy_cleanup_info(info);
+ return false;
+}
+
static void __handle_sigchild(int pid, void *user_data)
{
candidate_process_context_t *cpc;
+ struct cleanup_info_s *info;
char *appid;
+ int ret = -1;
appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid));
if (appid) {
- _W("security_manager_cleanup_app() ++");
- security_manager_cleanup_app(appid, getuid(), pid);
- _W("security_manager_cleanup_app() --");
+ info = __create_cleanup_info(appid, pid);
+ if (info)
+ ret = _worker_add_job(__cleanup_app_cb, info);
+
+ if (ret != 0) {
+ __destroy_cleanup_info(info);
+ _W("security_manager_cleanup_app() ++");
+ security_manager_cleanup_app(appid, getuid(), pid);
+ _W("security_manager_cleanup_app() --");
+ }
+
g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
}
return -1;
}
+ ret = _worker_init();
+ if (ret < 0)
+ return ret;
+
__register_vconf_events();
__init_app_defined_loader_monitor();
_memory_monitor_init();
_log_fini();
_memory_monitor_fini();
__unregister_vconf_events();
+ _worker_fini();
if (__pid_table)
g_hash_table_destroy(__pid_table);
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "launchpad_worker.h"
+#include "log_private.h"
+
+struct job_s {
+ worker_job_cb callback;
+ void *user_data;
+};
+
+struct worker_s {
+ GThread *thread;
+ GMutex mutex;
+ GCond cond;
+ GQueue *queue;
+};
+
+static struct worker_s __worker;
+
+int _worker_add_job(worker_job_cb callback, void *user_data)
+{
+ struct job_s *job;
+
+ if (!callback) {
+ _E("Invalid parameter");
+ return -EINVAL;
+ }
+
+ job = malloc(sizeof(struct job_s));
+ if (!job) {
+ _E("Out of memory");
+ return -ENOMEM;
+ }
+
+ job->callback = callback;
+ job->user_data = user_data;
+
+ g_mutex_lock(&__worker.mutex);
+ g_queue_push_tail(__worker.queue, job);
+ g_cond_signal(&__worker.cond);
+ g_mutex_unlock(&__worker.mutex);
+
+ return 0;
+}
+
+static int __set_comm(const char *name)
+{
+ int fd;
+ ssize_t bytes_written;
+ char path[PATH_MAX];
+ pid_t tid = syscall(__NR_gettid);
+
+ _I("[%s] TID(%d)", name, tid);
+ snprintf(path, sizeof(path), "/proc/%d/comm", tid);
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ _E("Failed to open %s. error(%d)", path, errno);
+ return -1;
+ }
+
+ bytes_written = write(fd, name, strlen(name) + 1);
+ if (bytes_written < 0) {
+ _E("Failed to write name(%s)", name);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static gpointer __worker_thread_cb(gpointer data)
+{
+ struct worker_s *worker = (struct worker_s *)data;
+ struct job_s *job;
+ bool done = false;
+
+ __set_comm("worker");
+ do {
+ g_mutex_lock(&worker->mutex);
+ if (g_queue_is_empty(worker->queue))
+ g_cond_wait(&worker->cond, &worker->mutex);
+
+ job = (struct job_s *)g_queue_pop_head(worker->queue);
+ g_mutex_unlock(&worker->mutex);
+ done = job->callback(job->user_data);
+ free(job);
+ } while (!done);
+
+ return NULL;
+}
+
+int _worker_init(void)
+{
+ _W("WORKER_INIT");
+
+ g_mutex_init(&__worker.mutex);
+ g_cond_init(&__worker.cond);
+
+ __worker.queue = g_queue_new();
+ if (!__worker.queue) {
+ _E("g_queue_new() is failed");
+ return -ENOMEM;
+ }
+
+ __worker.thread = g_thread_new("worker", __worker_thread_cb, &__worker);
+ if (!__worker.thread) {
+ _E("g_thread_new() is failed");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static bool __worker_done_cb(void *user_data)
+{
+ _W("Done");
+ return true;
+}
+
+void _worker_fini(void)
+{
+ _W("WORKER_FINI");
+
+ if (__worker.thread) {
+ _worker_add_job(__worker_done_cb, NULL);
+ g_thread_join(__worker.thread);
+ }
+
+ if (__worker.queue)
+ g_queue_free_full(__worker.queue, (GDestroyNotify)free);
+
+ g_cond_clear(&__worker.cond);
+ g_mutex_clear(&__worker.mutex);
+}