#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/signalfd.h>
#include <signal.h>
#include <grp.h>
+#include <fcntl.h>
#include <glib.h>
#include <gio/gio.h>
#define EXT_STORAGE_APPDATA_GROUP 10002
#define MEDIA_STORAGE_GROUP 10502
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+#define MAX_LONGLONG_LENGTH 32
typedef struct {
char **env;
*/
static char backend_busy = 0;
extern int num_of_backends;
+bool is_drm_busy = false;
-struct signal_info_t {
- pid_t pid;
- int status;
-};
-
-static int pipe_sig[2];
-static GIOChannel *pipe_io;
-static guint pipe_wid;
+static GIOChannel *sio;
+static guint swid;
static GHashTable *backend_info_table;
-static GMainLoop *mainloop = NULL;
+static GMainLoop *mainloop;
static int __check_backend_status_for_exit(void);
static int __check_queue_status_for_exit(void);
static int __is_backend_busy(int position);
static void __set_backend_busy(int position);
static void __set_backend_free(int position);
-static void sighandler(int signo);
gboolean exit_server(void *data);
backend_busy = backend_busy & ~(1 << position);
}
-static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond,
+static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
gpointer data)
{
GError *err = NULL;
GIOStatus s;
gsize len;
- struct signal_info_t info;
- struct backend_job *job;
+ char buf[MAX_LONGLONG_LENGTH];
+ long long result = 0;
+ struct backend_job *job = (struct backend_job *)data;
- s = g_io_channel_read_chars(io, (gchar *)&info,
- sizeof(struct signal_info_t), &len, &err);
+ s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
if (s != G_IO_STATUS_NORMAL) {
- ERR("Signal pipe read failed: %s", err->message);
+ ERR("getsize fd read failed: %s", err->message);
+ g_error_free(err);
+ result = -1;
+ } else {
+ if (strlen(buf) == 0) {
+ ERR("empty result");
+ result = -1;
+ } else {
+ result = atoll(buf);
+ }
+ }
+
+ _return_value_to_caller(job->req_id, g_variant_new("(ix)",
+ (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
+
+ unlink(job->extra->getsize_fifo);
+ free(job->extra->getsize_fifo);
+ job->extra->getsize_fifo = NULL;
+
+ return FALSE;
+}
+
+static int __setup_size_info_io(struct backend_job *job)
+{
+ guint getsize_wid;
+
+ job->extra->getsize_fd = open(job->extra->getsize_fifo,
+ O_RDONLY | O_NONBLOCK);
+ if (job->extra->getsize_fd < 0) {
+ ERR("failed to open the fifo(%s), errno(%d)",
+ job->extra->getsize_fifo, errno);
+ return -1;
+ }
+
+ job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
+ if (!job->extra->getsize_io)
+ return -1;
+ g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
+ g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
+ getsize_wid = g_io_add_watch(job->extra->getsize_io,
+ G_IO_IN, getsize_io_handler, job);
+ if (!getsize_wid) {
+ ERR("failed to add io watch");
+ return -1;
+ }
+
+ return 0;
+}
+
+static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
+ gpointer data)
+{
+ GError *err = NULL;
+ GIOStatus s;
+ gsize len;
+ struct signalfd_siginfo fdsi;
+ struct backend_job *job;
+ pid_t pid;
+ int status;
+
+ s = g_io_channel_read_chars(io, (gchar *)&fdsi,
+ sizeof(struct signalfd_siginfo), &len, &err);
+ if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
+ ERR("Signal read failed");
g_error_free(err);
return TRUE;
}
+ pid = waitpid(-1, &status, WNOHANG);
job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
- (gconstpointer)info.pid);
+ (gconstpointer)pid);
if (job == NULL) {
ERR("Unknown child exit");
return -1;
}
__set_backend_free(job->backend_slot);
- if (WIFSIGNALED(info.status)) {
+ if (WIFSIGNALED(status)) {
_send_fail_signal(job);
- DBG("backend[%s] exit with signal[%d]", job->backend_type,
- WTERMSIG(info.status));
- } else if (WEXITSTATUS(info.status)) {
- DBG("backend[%s] exit with error", job->backend_type);
+ INFO("backend[%s][%d] exit with signal[%d]", job->backend_type,
+ pid, WTERMSIG(status));
+ } else if (WEXITSTATUS(status)) {
+ INFO("backend[%s][%d] exit with error", job->backend_type, pid);
} else {
- DBG("backend[%s] exit", job->backend_type);
+ INFO("backend[%s][%d] exit", job->backend_type, pid);
+ }
+
+ if (job->extra) {
+ if (job->extra->getsize_fifo) {
+ ERR("invalid backend close");
+ _return_value_to_caller(job->req_id,
+ g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
+ }
}
- g_hash_table_remove(backend_info_table, (gconstpointer)info.pid);
+ g_hash_table_remove(backend_info_table, (gconstpointer)pid);
g_idle_add(queue_job, NULL);
return TRUE;
g_direct_equal, NULL,
(GDestroyNotify)_free_backend_job);
- if (pipe(pipe_sig)) {
- ERR("create pipe failed");
- return -1;
- }
-
- pipe_io = g_io_channel_unix_new(pipe_sig[0]);
- g_io_channel_set_encoding(pipe_io, NULL, NULL);
- g_io_channel_set_buffered(pipe_io, FALSE);
- pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
-
return 0;
}
static void __fini_backend_info(void)
{
- g_source_remove(pipe_wid);
- g_io_channel_unref(pipe_io);
- close(pipe_sig[0]);
- close(pipe_sig[1]);
-
/*Free backend info */
g_hash_table_destroy(backend_info_table);
}
-static void sighandler(int signo)
-{
- struct signal_info_t info;
- char buf[1024] = {0, };
-
- info.pid = waitpid(-1, &info.status, WNOHANG);
- if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
- ERR("failed to write result: %s",
- strerror_r(errno, buf, sizeof(buf)));
-}
-
static int __register_signal_handler(void)
{
- static int sig_reg = 0;
- struct sigaction act;
+ sigset_t mask;
+ int sfd;
- if (sig_reg)
- return 0;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
- act.sa_handler = sighandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_NOCLDSTOP;
- if (sigaction(SIGCHLD, &act, NULL) < 0) {
- ERR("signal: SIGCHLD failed");
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
+ ERR("sigprocmask failed");
return -1;
}
+ sfd = signalfd(-1, &mask, SFD_NONBLOCK);
+ if (sfd == -1) {
+ ERR("signalfd failed");
+ return -1;
+ }
+
+ sio = g_io_channel_unix_new(sfd);
+ g_io_channel_set_close_on_unref(sio, TRUE);
+ g_io_channel_set_encoding(sio, NULL, NULL);
+ g_io_channel_set_buffered(sio, FALSE);
+ swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
+
g_timeout_add_seconds(2, exit_server, NULL);
- sig_reg = 1;
return 0;
}
{
DBG("exit_server Start");
if (__check_backend_status_for_exit() &&
- __check_queue_status_for_exit()) {
+ __check_queue_status_for_exit() && !is_drm_busy) {
g_main_loop_quit(mainloop);
return FALSE;
}
return 0;
}
-void free_user_context(user_ctx* ctx)
+void free_user_context(user_ctx *ctx)
{
char **env = NULL;
int i = 0;
ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
if (FALSE == ret_parse) {
- DBG("Failed to split args: %s", args);
- DBG("messsage: %s", gerr->message);
+ ERR("Failed to split args: %s", args);
+ ERR("messsage: %s", gerr->message);
exit(1);
}
user_ctx *ctx = (user_ctx *)user_data;
if (set_environement(ctx))
- DBG("Failed to set env for the user : %d", ctx->uid);
+ ERR("Failed to set env for the user : %d", ctx->uid);
}
static int __fork_and_exec_with_args(char **argv, uid_t uid)
{
- user_ctx* user_context;
+ user_ctx *user_context;
GError *error = NULL;
gboolean ret;
int pid;
user_context = get_user_context(uid);
if (!user_context) {
- DBG("Failed to getenv");
+ ERR("Failed to getenv");
return -1;
}
if (ret != TRUE) {
ERR("Failed to excute backend: %s", error->message);
g_error_free(error);
+ free_user_context(user_context);
+ return -1;
}
free_user_context(user_context);
if (ret != PMINFO_R_OK)
goto catch;
- if ((job->req_type == REQUEST_TYPE_DISABLE_APP ||
- job->req_type == REQUEST_TYPE_ENABLE_APP) &&
- *is_global) {
- ret = PMINFO_R_ERROR;
- goto catch;
- } else if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
- job->req_type ==
- REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
+ if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
+ job->req_type ==
+ REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
!*is_global) {
ret = PMINFO_R_ERROR;
goto catch;
char *backend_cmd;
char **argv;
char args[MAX_PKG_ARGS_LEN];
+ gchar *req_id;
+ gchar *pkgid;
int pid;
backend_cmd = job->backend_path;
if (backend_cmd == NULL)
return -1;
+ req_id = g_shell_quote(job->req_id);
+ pkgid = g_shell_quote(job->pkgid);
+ if (!req_id || !pkgid)
+ return -1;
+
snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
- job->req_id, job->pkgid, (int)job->target_uid, job->args);
+ req_id, pkgid, (int)job->target_uid, job->args);
argv = __generate_argv(args);
pid = __fork_and_exec_with_args(argv, APPFW_UID);
g_strfreev(argv);
+ g_free(req_id);
+ g_free(pkgid);
return pid;
}
char *backend_cmd;
char **argv;
char args[MAX_PKG_ARGS_LEN];
+ gchar *req_id;
+ gchar *pkgid;
int pid;
backend_cmd = job->backend_path;
if (backend_cmd == NULL)
return -1;
+ req_id = g_shell_quote(job->req_id);
+ pkgid = g_shell_quote(job->pkgid);
+ if (!req_id || !pkgid)
+ return -1;
+
snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
- job->req_id, job->pkgid, (int)job->target_uid, job->args);
+ req_id, pkgid, (int)job->target_uid, job->args);
argv = __generate_argv(args);
pid = __fork_and_exec_with_args(argv, APPFW_UID);
g_strfreev(argv);
+ g_free(req_id);
+ g_free(pkgid);
return pid;
}
char *backend_cmd;
char **argv;
char args[MAX_PKG_ARGS_LEN];
+ gchar *req_id;
+ gchar *pkgid;
int pid;
backend_cmd = job->backend_path;
if (backend_cmd == NULL)
return -1;
+ req_id = g_shell_quote(job->req_id);
+ pkgid = g_shell_quote(job->pkgid);
+ if (!req_id || !pkgid)
+ return -1;
+
snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
- job->req_id, job->pkgid, (int)job->target_uid);
+ req_id, pkgid, (int)job->target_uid);
argv = __generate_argv(args);
pid = __fork_and_exec_with_args(argv, APPFW_UID);
g_strfreev(argv);
+ g_free(req_id);
+ g_free(pkgid);
return pid;
}
if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
_send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
PKGMGR_INSTALLER_START_KEY_STR,
- PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID,
+ PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
job->req_type);
_send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
PKGMGR_INSTALLER_END_KEY_STR,
_send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
PKGMGR_INSTALLER_START_KEY_STR,
- PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID,
+ PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
job->req_type);
ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
_send_app_signal(job->target_uid, job->req_id,
job->pkgid, job->pkgid,
PKGMGR_INSTALLER_START_KEY_STR,
- PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID,
+ PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
job->req_type);
_send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
PKGMGR_INSTALLER_END_KEY_STR,
_send_app_signal(job->target_uid, job->req_id,
job->pkgid, job->appid,
PKGMGR_INSTALLER_START_KEY_STR,
- PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID,
+ PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
job->req_type);
ret = __kill_app(job->appid, job->target_uid);
return pid;
}
+static int __process_getsize_sync(struct backend_job *job)
+{
+ static const char backend_cmd[] = "/usr/bin/pkg_getsize";
+ char **argv;
+ char args[MAX_PKG_ARGS_LEN];
+ char fifo_path[PATH_MAX];
+ int pid;
+
+ snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
+ job->req_id);
+
+ job->extra = calloc(1, sizeof(struct job_extra_info));
+ if (!job->extra) {
+ ERR("memory alloc failed");
+ goto error;
+ }
+
+ job->extra->getsize_fifo = strdup(fifo_path);
+ if (!job->extra->getsize_fifo) {
+ ERR("out of memory");
+ goto error;
+ }
+
+ if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
+ ERR("failed to mkfifo");
+ goto error;
+ }
+
+ snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
+ backend_cmd, job->pkgid, job->args, job->caller_uid,
+ job->req_id, job->target_uid);
+ argv = __generate_argv(args);
+ pid = __fork_and_exec_with_args(argv, APPFW_UID);
+
+ g_strfreev(argv);
+
+ if (pid < 0) {
+ ERR("failed to execute backend");
+ goto error;
+ }
+ if (__setup_size_info_io(job) < 0) {
+ ERR("failed to setup io handler");
+ goto error;
+ }
+
+ return pid;
+
+error:
+ _return_value_to_caller(job->req_id,
+ g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
+ return -1;
+}
+
static int __process_cleardata(struct backend_job *job)
{
- char *backend_cmd;
+ static const char *backend_cmd = "/usr/bin/pkg_cleardata";
char **argv;
char args[MAX_PKG_ARGS_LEN];
int pid;
- backend_cmd = job->backend_path;
- if (backend_cmd == NULL)
+ if ((int)job->target_uid < REGULAR_USER)
return -1;
- /* TODO: set movetype */
- snprintf(args, sizeof(args), "%s -k %s -c %s -u %d", backend_cmd,
- job->req_id, job->pkgid, (int)job->target_uid);
+ snprintf(args, sizeof(args), "%s -d -n %s -u %d",
+ backend_cmd, job->pkgid, job->target_uid);
argv = __generate_argv(args);
-
pid = __fork_and_exec_with_args(argv, APPFW_UID);
g_strfreev(argv);
-
return pid;
}
static int __process_clearcache(struct backend_job *job)
{
- static const char *backend_cmd = "/usr/bin/pkg_clearcache";
+ static const char *backend_cmd = "/usr/bin/pkg_cleardata";
char **argv;
char args[MAX_PKG_ARGS_LEN];
int pid;
- snprintf(args, sizeof(args), "%s %s", backend_cmd, job->pkgid);
+ if ((int)job->target_uid < REGULAR_USER)
+ return -1;
+
+ snprintf(args, sizeof(args), "%s -c -n %s -u %d",
+ backend_cmd, job->pkgid, job->target_uid);
argv = __generate_argv(args);
- pid = __fork_and_exec_with_args(argv, job->target_uid);
+ pid = __fork_and_exec_with_args(argv, APPFW_UID);
g_strfreev(argv);
-
return pid;
}
ERR("drm_tizen_generate_license_request failed: %d", ret);
_return_value_to_caller(job->req_id, g_variant_new("(iss)",
PKGMGR_R_ESYSTEM, "", ""));
+ is_drm_busy = false;
return -1;
}
_return_value_to_caller(job->req_id,
g_variant_new("(iss)", PKGMGR_R_OK, req_data,
license_url));
-
+ is_drm_busy = true;
return 0;
}
ERR("drm_tizen_register_license failed: %d", ret);
_return_value_to_caller(job->req_id,
g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ is_drm_busy = false;
return -1;
}
ERR("drm_tizen_register_license failed: %d", ret);
_return_value_to_caller(job->req_id,
g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ is_drm_busy = false;
return -1;
}
_return_value_to_caller(job->req_id,
g_variant_new("(i)", PKGMGR_R_OK));
+ is_drm_busy = false;
return 0;
}
return ret;
}
+static int __process_migrate_external_image(struct backend_job *job)
+{
+ char *backend_cmd;
+ char **argv;
+ char args[MAX_PKG_ARGS_LEN];
+ int pid;
+
+ backend_cmd = job->backend_path;
+ if (backend_cmd == NULL)
+ return -1;
+
+ snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
+ backend_cmd, job->req_id, job->pkgid,
+ (int)job->target_uid, job->args);
+
+ argv = __generate_argv(args);
+
+ pid = __fork_and_exec_with_args(argv, APPFW_UID);
+ g_strfreev(argv);
+
+ return pid;
+}
+
+static int __post_process(int ret, int x, struct backend_job *job)
+{
+ if (ret < 0) {
+ __set_backend_free(x);
+ _free_backend_job(job);
+ } else {
+ g_hash_table_insert(backend_info_table, (gpointer)ret,
+ (gpointer)job);
+ }
+ return 0;
+}
+
gboolean queue_job(void *data)
{
struct backend_job *job = NULL;
/* all backend messages queue are empty or busy */
if (x == num_of_backends || job == NULL) {
- DBG("no job left");
+ DBG("no job available");
return FALSE;
}
ret = -1;
_send_fail_signal(job);
_free_backend_job(job);
- return FALSE;
+ return TRUE;
}
}
#endif
case REQUEST_TYPE_INSTALL:
__set_backend_busy(x);
ret = __process_install(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_MOUNT_INSTALL:
__set_backend_busy(x);
ret = __process_mount_install(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_REINSTALL:
__set_backend_busy(x);
ret = __process_reinstall(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_UNINSTALL:
__set_backend_busy(x);
ret = __process_uninstall(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_MOVE:
__set_backend_busy(x);
ret = __process_move(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_ENABLE_PKG:
__set_backend_busy(x);
ret = __process_enable_pkg(job);
- if (ret == -1) {
+ if (ret < 0)
_send_fail_signal(job);
- __set_backend_free(x);
- _free_backend_job(job);
- } else {
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
- }
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_DISABLE_PKG:
__set_backend_busy(x);
ret = __process_disable_pkg(job);
- if (ret == -1) {
+ if (ret < 0)
_send_fail_signal(job);
- __set_backend_free(x);
- _free_backend_job(job);
- } else {
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
- }
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_ENABLE_APP:
ret = __process_enable_app(job);
case REQUEST_TYPE_GETSIZE:
__set_backend_busy(x);
ret = __process_getsize(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
+ break;
+ case REQUEST_TYPE_GETSIZE_SYNC:
+ __set_backend_busy(x);
+ ret = __process_getsize_sync(job);
+ if (ret < 0)
+ __free_extra_info(job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_CLEARDATA:
__set_backend_busy(x);
ret = __process_cleardata(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_CLEARCACHE:
__set_backend_busy(x);
ret = __process_clearcache(job);
- g_hash_table_insert(backend_info_table, (gpointer)ret,
- (gpointer)job);
+ __post_process(ret, x, job);
break;
case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
ret = __process_enable_global_app_for_uid(job);
ret = __process_set_app_label(job);
_free_backend_job(job);
break;
+ case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
+ __set_backend_busy(x);
+ ret = __process_migrate_external_image(job);
+ __post_process(ret, x, job);
+ break;
default:
ret = -1;
break;
}
- return FALSE;
+ return TRUE;
}
int main(int argc, char *argv[])
DBG("server start");
+ if (__register_signal_handler()) {
+ ERR("failed to register signal handler");
+ return -1;
+ }
+
r = _init_backend_queue();
if (r) {
- DBG("Queue Initialization Failed");
+ ERR("Queue Initialization Failed");
return -1;
}
r = __init_backend_info();
if (r) {
- DBG("backend info init failed");
+ ERR("backend info init failed");
return -1;
}
return -1;
}
- if (__register_signal_handler()) {
- ERR("failed to register signal handler");
- return -1;
- }
-
#if !GLIB_CHECK_VERSION(2, 35, 0)
g_type_init();
#endif
__fini_backend_info();
_fini_backend_queue();
+ g_source_remove(swid);
+ g_io_channel_unref(sio);
+
DBG("package manager server terminated.");
return 0;