#include <gio/gio.h>
#include <fcntl.h>
#include <string.h>
+#include <libcrash-service.h>
#include "utils.h"
#include "log.h"
free(ad);
}
-static void crash_manager_exit_cb(GPid pid, gint status, gpointer user_data)
+static void livedump_pid_thread_cb(GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
{
- struct action_data *ad = user_data;
- FILE *stream = NULL;
- char *line = NULL;
- size_t len = 0;
- ssize_t n;
-
- if (!g_spawn_check_exit_status (status, NULL)) {
- _E("Crash-manager failed with code: %d", status);
-
- stream = fdopen(ad->stderr_fd, "r");
- if (!stream) {
- _E("Unable to open stderr stream: %m");
- goto finish;
- }
-
- while ((n = getline(&line, &len, stream)) != -1)
- _D("%s", line);
-
- goto finish;
- }
-
- stream = fdopen(ad->stdout_fd, "r");
- if (!stream) {
- _E("Unable to open stdout stream: %m");
+ struct action_data *ad = task_data;
+ char reason[4096];
+ int ret;
+ char *actual_str = g_variant_print(ad->actual_value, TRUE);
+ char *allowed_str = g_variant_print(ad->allowed_value, TRUE);
+
+ ret = sprintf(reason, "Stability-monitor detected abnormality.\n"
+ "Process name: %s\n"
+ "PID: %d\n"
+ "Exceeded parameter: %s\n"
+ "Actual value: %s\n"
+ "Allowed value: %s\n",
+ ad->ds->process->name,
+ ad->ds->process->pid,
+ ad->ds->param_name,
+ actual_str,
+ allowed_str);
+ if (ret == -1) {
+ _E("Couldn't print dbus object path: %m");
goto finish;
}
- /* Get report path from stdout */
- while ((n = getline(&line, &len, stream)) != -1) {
- if (strncmp(line, "REPORT_PATH=", 12) == 0) {
- line[n-1] = 0;
-
- ad->report_path = strndup(line + 12, n - 12);
- if (!ad->report_path)
- _E("Unable to allocate memory");
- else
- _D_PROC(ad->ds->process, "Received report: %s", ad->report_path);
-
- goto finish;
- }
- }
-
- _E("Crash-worker ended without error but didn't provide report path");
+ ret = (livedump_pid(ad->ds->process->pid, reason, ad->report_path, PATH_MAX) == FALSE);
finish:
- action_finish(ad); // NB: also closes `stream` through `ad->stdout_fd`
-
- free(line);
- g_spawn_close_pid(pid);
+ free(actual_str);
+ free(allowed_str);
+ g_task_return_int(task, ret);
}
-static GPid spawn_crash_manager(struct action_data *ad)
+void livedump_pid_async(GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GPid child_pid = 0;
- GError *error = NULL;
- char *pid_str = NULL;
- if (asprintf(&pid_str, "%d", ad->ds->process->pid) == -1)
- goto out;
-
- char *argv[] = {CRASH_MANAGER_BIN, "-lrp", pid_str, NULL};
-
- _D_PROC(ad->ds->process, "Generating report...");
-
- /* Spawn child */
- if (!g_spawn_async_with_pipes(NULL, argv, NULL,
- G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL,
- NULL, &child_pid, NULL, &ad->stdout_fd, &ad->stderr_fd, &error)) {
-
- _E("Unable to spawn child process: %s", error->message);
- g_error_free(error);
- }
- _D("Spawned child process pid %d", child_pid);
+ struct action_data *ad = user_data;
+ GTask *task = g_task_new(NULL, NULL, callback, user_data);
-out:
- free(pid_str);
- return child_pid;
+ g_task_set_source_tag(task, livedump_pid_async);
+ g_task_set_task_data(task, ad, NULL);
+ g_task_run_in_thread(task, livedump_pid_thread_cb);
+ g_object_unref(task);
}
-static gboolean action_run(gpointer data)
+static void on_livedump_complete(GObject *gobject,
+ GAsyncResult *result,
+ gpointer user_data)
{
- struct action_data *ad = data;
- GPid child_pid;
-
- if (ad->ds->process->report) {
- child_pid = spawn_crash_manager(ad);
- if (child_pid != 0) {
- g_child_watch_add(child_pid, crash_manager_exit_cb, ad);
- return FALSE;
- }
+ struct action_data *ad = user_data;
+ int ret;
+
+ ret = g_task_propagate_int(G_TASK(result), NULL);
+ if (ret) {
+ _E("livedump_pid() failed (for more info please check 'dlogutil LIBCRASH-SERVICE' and/or 'dlogutil CRASH_MANAGER'");
+ ad->report_path[0] = 0;
+ } else {
+ _D_PROC(ad->ds->process, "Received report: %s", ad->report_path);
}
action_finish(ad);
-
- return FALSE;
}
int action_run_default(struct data_source *ds, enum limit_type lt)
return -ENOMEM;
}
+ ad->report_path = calloc(1, PATH_MAX);
+ if (!ad->report_path) {
+ _E("Unable to allocate memory");
+ free(ad);
+ return -ENOMEM;
+ }
+
ad->ds = ds;
- ad->report_path = NULL;
ad->lt = lt;
if (lt == LIMIT_TYPE_AVG) {
}
process_ref(ds->process);
- g_timeout_add(0, action_run, ad);
+ if (ad->ds->process->report)
+ livedump_pid_async(on_livedump_complete, ad);
+ else
+ action_finish(ad);
return 0;
}