*
* Connection Manager
*
- * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
static GHashTable *task_hash = NULL;
-static volatile gint task_counter;
+static volatile int task_counter;
static DBusConnection *connection;
DBG("");
task = g_try_new0(struct connman_task, 1);
- if (task == NULL)
+ if (!task)
return NULL;
- counter = g_atomic_int_exchange_and_add(&task_counter, 1);
+ counter = __sync_fetch_and_add(&task_counter, 1);
task->path = g_strdup_printf("/task/%d", counter);
task->pid = -1;
DBG("task %p arg %s", task, name);
- if (name == NULL)
+ if (!name)
return -EINVAL;
str = g_strdup(name);
va_start(ap, format);
- if (format != NULL) {
+ if (format) {
str = g_strdup_vprintf(format, ap);
g_ptr_array_add(task->argv, str);
}
DBG("task %p key %s", task, key);
- if (key == NULL)
+ if (!key)
return -EINVAL;
va_start(ap, format);
DBG("task %p", task);
notify = g_try_new0(struct notify_data, 1);
- if (notify == NULL)
+ if (!notify)
return -ENOMEM;
notify->func = function;
notify->data = user_data;
- g_hash_table_insert(task->notify, g_strdup(member), notify);
+ g_hash_table_replace(task->notify, g_strdup(member), notify);
return 0;
}
int *stdin_fd, int *stdout_fd, int *stderr_fd)
{
GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
- gboolean result;
+ bool result;
char **argv, **envp;
DBG("task %p", task);
if (task->pid > 0)
return -EALREADY;
- if (stdout_fd == NULL)
+ if (!stdout_fd)
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
- if (stderr_fd == NULL)
+ if (!stderr_fd)
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
task->exit_func = function;
task->exit_data = user_data;
- if (g_ptr_array_index(task->argv, task->argv->len - 1) != NULL)
+ if (g_ptr_array_index(task->argv, task->argv->len - 1))
g_ptr_array_add(task->argv, NULL);
- if (task->envp->len == 0 || g_ptr_array_index(task->envp,
- task->envp->len - 1) != NULL) {
+ if (task->envp->len == 0 ||
+ g_ptr_array_index(task->envp, task->envp->len - 1)) {
if (g_hash_table_size(task->notify) > 0) {
const char *busname;
char *str;
result = g_spawn_async_with_pipes(NULL, argv, envp, flags,
task_setup, task, &task->pid,
stdin_fd, stdout_fd, stderr_fd, NULL);
- if (result == FALSE) {
+ if (!result) {
connman_error("Failed to spawn %s", argv[0]);
return -EIO;
}
return 0;
}
+static gboolean force_kill_timeout(gpointer user_data)
+{
+ pid_t pid = GPOINTER_TO_INT(user_data);
+ if (pid > 0) {
+ if (kill(pid, SIGKILL) == 0)
+ connman_warn("killing pid %d by force", pid);
+ }
+
+ return FALSE;
+}
+
+static gboolean kill_timeout(gpointer user_data)
+{
+ pid_t pid = GPOINTER_TO_INT(user_data);
+ if (pid > 0) {
+ if (kill(pid, SIGINT) == 0)
+ g_timeout_add_seconds(1, force_kill_timeout,
+ GINT_TO_POINTER(pid));
+ }
+
+ return FALSE;
+}
+
+static gboolean check_kill(gpointer user_data)
+{
+ pid_t pid = GPOINTER_TO_INT(user_data);
+ if (pid > 0) {
+ if (kill(pid, 0) == 0) {
+ connman_info("pid %d was not killed, "
+ "retrying after 2 sec", pid);
+ g_timeout_add_seconds(2, kill_timeout,
+ GINT_TO_POINTER(pid));
+ }
+ }
+
+ return FALSE;
+}
+
/**
* connman_task_stop:
* @task: task structure
{
DBG("task %p", task);
- if (task->pid > 0)
+ if (task->pid > 0) {
kill(task->pid, SIGTERM);
+ g_idle_add(check_kill, GINT_TO_POINTER(task->pid));
+ }
+
return 0;
}
-static DBusHandlerResult task_filter(DBusConnection *connection,
+static DBusHandlerResult task_filter(DBusConnection *conn,
DBusMessage *message, void *user_data)
{
struct connman_task *task;
struct notify_data *notify;
const char *path, *member;
+ DBusMessage *reply = NULL;
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- if (dbus_message_has_interface(message,
- CONNMAN_TASK_INTERFACE) == FALSE)
+ if (!dbus_message_has_interface(message, CONNMAN_TASK_INTERFACE))
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
path = dbus_message_get_path(message);
- if (path == NULL)
+ if (!path)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
task = g_hash_table_lookup(task_hash, path);
- if (task == NULL)
+ if (!task)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- if (dbus_message_get_no_reply(message) == FALSE) {
- DBusMessage *reply;
+ member = dbus_message_get_member(message);
+ if (!member)
+ goto send_reply;
+
+ notify = g_hash_table_lookup(task->notify, member);
+ if (!notify)
+ goto send_reply;
+
+ if (notify->func)
+ reply = notify->func(task, message, notify->data);
+
+send_reply:
+ if (!dbus_message_get_no_reply(message) &&
+ !reply) {
reply = dbus_message_new_method_return(message);
- if (reply == NULL)
+ if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
- dbus_connection_send(connection, reply, NULL);
+ if (reply) {
+ dbus_connection_send(conn, reply, NULL);
dbus_message_unref(reply);
}
- member = dbus_message_get_member(message);
- if (member == NULL)
- return DBUS_HANDLER_RESULT_HANDLED;
-
- notify = g_hash_table_lookup(task->notify, member);
- if (notify == NULL)
- return DBUS_HANDLER_RESULT_HANDLED;
-
- if (notify->func)
- notify->func(task, message, notify->data);
-
return DBUS_HANDLER_RESULT_HANDLED;
}
dbus_connection_add_filter(connection, task_filter, NULL, NULL);
- g_atomic_int_set(&task_counter, 0);
+ task_counter = 0;
+ __sync_synchronize();
task_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, free_task);