#include <unistd.h>
#include <diagnostics.h>
#include <unistd.h>
+#include <signal.h>
#include "bugreport-service.h"
#define TIMEOUT_INTERVAL_SEC 60
#define TIMEOUT_LIVEDUMP_SEC 50
-#define CS_ERROR 1
-#define CS_ERR_PARAM 1
-#define CS_ERR_TIMEOUT 2
-#define CS_ERR_READ 3
-#define CS_ERR_INTERNAL 4
-#define CS_ERR_UNSUPPORTED 5
-
static GMainLoop *loop;
static GMutex timeout_mutex;
static guint timeout_id;
{
struct callback_data *cb_data = (struct callback_data*)data;
char report_path[PATH_MAX] = {0};
+ bool error_sent = false;
if (!data_ready(cb_data->read_fd)) {
_I("Report is not ready after %d seconds.", TIMEOUT_LIVEDUMP_SEC);
CS_ERR_TIMEOUT,
"Report is not ready");
kill(cb_data->child_pid, SIGKILL);
- goto end;
- } else {
- if (read(cb_data->read_fd, report_path, sizeof(report_path)) == -1) {
- _E("Read from child error: %m");
+ error_sent = true;
+ } else if (read(cb_data->read_fd, report_path, sizeof(report_path)) == -1) {
+ _E("Read from child error: %m");
+ g_dbus_method_invocation_return_error(cb_data->invocation,
+ CS_ERROR,
+ CS_ERR_READ,
+ "Error while obtaining report path");
+ error_sent = true;
+ }
+
+ close(cb_data->read_fd);
+ int status;
+ if (waitpid(cb_data->child_pid, &status, 0) == -1 && !error_sent) {
+ g_dbus_method_invocation_return_error(cb_data->invocation,
+ CS_ERROR,
+ CS_ERR_INTERNAL,
+ "Internal error");
+ error_sent = true;
+ }
+
+ if (!error_sent && WIFEXITED(status)) {
+ int exit_status = WEXITSTATUS(status);
+ if (exit_status != CS_ERR_NO_ERROR) {
+ _E("Child process returned an error code: %d", exit_status);
g_dbus_method_invocation_return_error(cb_data->invocation,
- CS_ERROR,
- CS_ERR_READ,
- "Error while obtaining report path");
- goto end;
+ CS_ERROR,
+ exit_status,
+ "Error");
+ error_sent = true;
}
}
- int res = diagnostics_send_event("BugreportCreated", NULL);
- if (res != DIAGNOSTICS_ERROR_NONE)
- _E("Send diagnostics event error: %d", res);
+ if (!error_sent) {
+ int res = diagnostics_send_event("BugreportCreated", NULL);
+ if (res != DIAGNOSTICS_ERROR_NONE)
+ _E("Send diagnostics event error: %d", res);
- g_dbus_method_invocation_return_value(cb_data->invocation,
- g_variant_new("(s)", report_path));
-end:
- close(cb_data->read_fd);
-
- waitpid(cb_data->child_pid, NULL, 0);
+ g_dbus_method_invocation_return_value(cb_data->invocation,
+ g_variant_new("(s)", report_path));
+ }
free(cb_data);
return G_SOURCE_REMOVE;
}
-static bool livedump_run(struct dump_operation_data *data)
+static int livedump_run(struct dump_operation_data *data)
{
assert(data);
+
+ if (kill(data->pid, 0) != 0) {
+ close(data->write_fd);
+ _E("No such process: %d", data->pid);
+ return CS_ERR_NO_PROC;
+ }
+
char report_path[PATH_MAX];
if (!crash_manager_livedump_pid(data->pid, data->dump_reason, report_path, sizeof(report_path))) {
_E("crash_manager_livedump_pid error");
- return false;
+ return CS_ERR_INTERNAL;
}
if (write(data->write_fd, report_path, strlen(report_path) + 1) == -1) {
_E("Write report_path error: %m");
close(data->write_fd);
- return false;
+ return CS_ERR_INTERNAL;
}
close(data->write_fd);
- return true;
+ return CS_ERR_NO_ERROR;
}
-static void dump_handler(GDBusMethodInvocation *invocation, bool (*operation)(struct dump_operation_data *), struct dump_operation_data *data)
+static void dump_handler(GDBusMethodInvocation *invocation, int (*operation)(struct dump_operation_data *), struct dump_operation_data *data)
{
/*
* We want to run the livedump in different process so as not to
if (child_pid == 0) {
close(fds[0]);
data->write_fd = fds[1];
- if (operation(data))
- exit(EXIT_SUCCESS);
- else
- exit(EXIT_FAILURE);
+ exit(operation(data));
} else if (child_pid > 0) {
cb_data->child_pid = child_pid;
close(fds[1]);