Add DBus signal emitting after report save 65/186565/6
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Thu, 2 Aug 2018 09:16:56 +0000 (11:16 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Wed, 22 Aug 2018 05:51:37 +0000 (07:51 +0200)
Interface: "org.tizen.system.crash.Crash"
Path: "/org/Tizen/System/Crash/Crash"
Signal: "ProcessCrashed"

Message (signature "sssssiia{sv}"), contains:
* process name
* exe path
* appid
* pkgid
* report path
* PID
* TID
* dictionary a{sv} contains registers values depends on the architecture:

    * for x86:
      * x86.eip

    * for x86_64:
      * x86_64.rip

    * for armv7l:
      * arm.pc
      * arm.lr

    * for aarch64:
      * aarch64.pc
      * aarch64.lr

Change-Id: I081a3f4982e2f0d4b01fd665b4dffcd3bab847f4

packaging/crash-worker.spec
src/crash-manager/CMakeLists.txt
src/crash-manager/crash-manager.c
src/crash-manager/dbus_notify.c [new file with mode: 0644]
src/crash-manager/dbus_notify.h [new file with mode: 0644]

index 5d41038..92eac66 100644 (file)
@@ -23,6 +23,7 @@ BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(rpm)
 BuildRequires:  cmake
+BuildRequires:  pkgconfig(pkgmgr-info)
 
 BuildRequires:  pkgconfig(libunwind-generic)
 %if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on"
index d70dde2..2b7e6e4 100644 (file)
@@ -17,6 +17,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
 SET(CRASH_MANAGER_SRCS
        crash-manager.c
        so-info.c
+       dbus_notify.c
        ${CMAKE_SOURCE_DIR}/src/shared/util.c
    )
 
@@ -26,6 +27,7 @@ pkg_check_modules(crash-manager_pkgs REQUIRED
        libtzplatform-config
        iniparser
        gio-2.0
+       pkgmgr-info
        rpm
        )
 
index 922f99e..2c351fe 100644 (file)
 #include <gio/gio.h>
 #include <iniparser.h>
 #include <tzplatform_config.h>
+#include <pkgmgr-info.h>
 #include "crash-manager.h"
 #include "so-info.h"
 #include "shared/log.h"
 #include "shared/util.h"
+#include "dbus_notify.h"
 
 #undef LOG_TAG
 #define LOG_TAG "CRASH_MANAGER"
@@ -63,6 +65,9 @@
 #define MAX_CRASH_DUMP       0
 #define ALLOW_ZIP            true
 
+#define APPID_MAX                   128
+#define PKGNAME_MAX                 128
+
 #define CRASH_CHECK_DISK_PATH "/opt/usr"
 #define WAIT_FOR_OPT_TIMEOUT_SEC 60
 
@@ -104,6 +109,8 @@ static struct crash_info {
        char info_path[PATH_MAX];
        char core_path[PATH_MAX];
        char log_path[PATH_MAX];
+       char appid[APPID_MAX];
+       char pkgid[PKGNAME_MAX];
 #ifdef SYS_ASSERT
        char sysassert_cs_path[PATH_MAX];
        bool have_sysassert_report;
@@ -111,6 +118,93 @@ static struct crash_info {
        int prstatus_fd;
 } crash_info;
 
+/* pkgmgrinfo filter list function for getting application ID */
+static int appinfo_get_appid_func(pkgmgrinfo_appinfo_h handle,
+               void *user_data)
+{
+       char *str = NULL;
+       int ret = PMINFO_R_ERROR;
+
+       pkgmgrinfo_appinfo_get_appid(handle, &str);
+       if (str) {
+               (*(char **)user_data) = strdup(str);
+               ret = PMINFO_R_OK;
+       }
+       return ret;
+}
+
+/* get application ID by pkgmgrinfo filter */
+static int get_appid(char *exepath, char *appid, int len)
+{
+       pkgmgrinfo_appinfo_filter_h handle = NULL;
+       int count, ret;
+       char *aid = NULL;
+
+       ret = pkgmgrinfo_appinfo_filter_create(&handle);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out;
+       }
+
+       ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_EXEC, exepath);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out_free;
+       }
+
+       ret = pkgmgrinfo_appinfo_filter_count(handle, &count);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out_free;
+       }
+
+       if (count < 1) {
+               ret = -1;
+               goto out_free;
+       }
+
+       ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appinfo_get_appid_func, &aid);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out_free;
+       }
+       if (aid) {
+               snprintf(appid, len, "%s", aid);
+               ret = 0;
+               free(aid);
+       }
+
+out_free:
+       pkgmgrinfo_appinfo_filter_destroy(handle);
+out:
+       return ret;
+}
+
+/* get package ID by appid */
+static int get_pkgid(char *appid, char *pkgid, int len)
+{
+       pkgmgrinfo_appinfo_h handle = NULL;
+       int ret;
+       char *pkid = NULL;
+
+       ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out;
+       }
+       ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkid);
+       if (ret != PMINFO_R_OK) {
+               ret = -1;
+               goto out_free;
+       }
+       snprintf(pkgid, len, "%s", pkid);
+
+out_free:
+       pkgmgrinfo_appinfo_destroy_appinfo(handle);
+out:
+       return ret;
+}
+
 static void get_config(void)
 {
        dictionary *ini = NULL;
@@ -415,6 +509,14 @@ static int set_crash_info(int argc, char *argv[])
        if (set_prstatus() < 0)
                goto rm_temp;
 
+       if (get_appid(crash_info.cmd_line, crash_info.appid, sizeof(crash_info.appid)) < 0) {
+               snprintf(crash_info.appid, sizeof(crash_info.appid), "%s", basename(crash_info.cmd_line));
+               snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", basename(crash_info.cmd_line));
+       } else {
+               if (get_pkgid(crash_info.appid, crash_info.pkgid, sizeof(crash_info.pkgid)) < 0)
+                       snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", crash_info.appid);
+       }
+
        return 0;
 
 rm_temp:
@@ -1025,6 +1127,19 @@ int main(int argc, char *argv[])
                launch_crash_popup();
 #endif
 
+       struct NotifyParams notify_params = {
+               .prstatus_fd = crash_info.prstatus_fd,
+               .pid = strtol(crash_info.pid_info, NULL, 10),
+               .tid = strtol(crash_info.tid_info, NULL, 10),
+               .cmd_name = basename(crash_info.cmd_line),
+               .cmd_path = crash_info.cmd_path,
+               .report_path = crash_info.result_path,
+               .appid = crash_info.appid,
+               .pkgid = crash_info.pkgid
+       };
+
+       send_notify(&notify_params);
+
        close(crash_info.prstatus_fd);
        return 0;
 }
diff --git a/src/crash-manager/dbus_notify.c b/src/crash-manager/dbus_notify.c
new file mode 100644 (file)
index 0000000..6a8c5d8
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ * Author: Mateusz Moscicki <m.moscicki2@partner.samsung.com>
+ */
+
+#define _GNU_SOURCE
+#include <gio/gio.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/procfs.h>
+#include "shared/log.h"
+#include "dbus_notify.h"
+
+#define KERNEL_DEFINED_TASK_COMM_LEN 16 // from include/linux/sched.h
+
+#define ARM_REG_LR 14
+#define ARM_REG_PC 15
+#define AARCH64_REG_LR 30
+
+static int _get_important_registers(int fd, struct RegInfo **reg_info)
+{
+       int count = -1;
+
+       if (reg_info == NULL) {
+               _E("reg_info is NULL\n");
+               return -1;
+       }
+
+       *reg_info = NULL;
+       struct elf_prstatus *prstatus = mmap(NULL, sizeof(struct elf_prstatus),
+                                        PROT_READ, MAP_SHARED, fd, 0);
+       if (prstatus == MAP_FAILED) {
+               _E("mmap error: %m\n");
+               return -1;
+       }
+
+#if (defined __i386__) || (defined __x86_64__)
+       count = 1;
+#elif (defined __arm__) || (defined __aarch64__)
+       count = 2;
+#endif
+
+       *reg_info = (struct RegInfo*)malloc(sizeof(struct RegInfo)*count);
+       struct RegInfo *reginfo = *reg_info;
+
+       if (*reg_info == NULL) {
+               _E("malloc for reg_info error: %m");
+               goto out;
+       }
+
+#if (defined __i386__) || (defined __x86_64__)
+       struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg;
+
+#if defined(__i386__)
+       reginfo[0].name = strdup("x86.eip");
+       reginfo[0].value = (long long int)g_registers->eip;
+#else
+       reginfo[0].name = strdup("x86_64.rip");
+       reginfo[0].value = (long long int)g_registers->rip;
+#endif // defined(__i386__)
+
+       if (reginfo[0].name == NULL)
+               goto strdup_error;
+
+#elif defined(__arm__)
+
+       struct user_regs *g_registers;
+       g_registers = (struct user_regs*)prstatus->pr_reg;
+
+       if ((reginfo[0].name = strdup("arm.pc")) == NULL)
+               goto strdup_error;
+       reginfo[0].value = (long long int)g_registers->uregs[ARM_REG_PC];
+       if ((reginfo[1].name = strdup("arm.lr")) == NULL)
+               goto strdup_error;
+       reginfo[1].value = (long long int)g_registers->uregs[ARM_REG_LR];
+
+#elif defined(__aarch64__)
+
+       struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg;
+
+       if ((reginfo[0].name = strdup("aarch64.pc")) == NULL)
+               goto strdup_error;
+       reginfo[0].value = (long long int)g_registers->pc;
+       if ((reginfo[1].name = strdup("aarch64.lr")) == NULL)
+               goto strdup_error;
+       reginfo[1].value = (long long int)g_registers->regs[AARCH64_REG_LR];
+
+#endif // (defined __i386__) || (defined __x86_64__)
+
+out:
+       if (count <= 0) {
+               free(*reg_info);
+               *reg_info = NULL;
+       }
+
+       munmap(prstatus, sizeof(*prstatus));
+       return count;
+
+strdup_error:
+       _E("strdup error: %m\n");
+       count = -1;
+       goto out;
+}
+
+static GVariant* build_message_data(const struct NotifyParams *notify_params)
+{
+       if (notify_params == NULL)
+               return NULL;
+
+       GVariantBuilder md_builder;
+       g_variant_builder_init(&md_builder, G_VARIANT_TYPE("(sssssiia{sv})"));
+
+       g_variant_builder_add(&md_builder, "s", notify_params->cmd_name);
+       g_variant_builder_add(&md_builder, "s", notify_params->cmd_path);
+       g_variant_builder_add(&md_builder, "s", notify_params->appid);
+       g_variant_builder_add(&md_builder, "s", notify_params->pkgid);
+       g_variant_builder_add(&md_builder, "s", notify_params->report_path);
+       g_variant_builder_add(&md_builder, "i", notify_params->pid);
+       g_variant_builder_add(&md_builder, "i", notify_params->tid);
+
+       g_variant_builder_open(&md_builder, G_VARIANT_TYPE("a{sv}"));
+
+       struct RegInfo *reg_info;
+       int regs_count = _get_important_registers(notify_params->prstatus_fd, &reg_info);
+
+       /* registers */
+       for (int i = 0; i < regs_count; i++) {
+               g_variant_builder_open(&md_builder, G_VARIANT_TYPE("{sv}"));
+
+               g_variant_builder_add(&md_builder, "s", reg_info[i].name);
+#if (defined __x86_64__) || (defined __aarch64__)
+               g_variant_builder_add(&md_builder, "v", g_variant_new_uint64(reg_info[i].value));
+#else
+               g_variant_builder_add(&md_builder, "v", g_variant_new_uint32(reg_info[i].value));
+#endif
+
+               free(reg_info[i].name);
+               g_variant_builder_close(&md_builder);
+       }
+       free(reg_info);
+
+       g_variant_builder_close(&md_builder);
+
+       return g_variant_builder_end(&md_builder);
+}
+
+int send_notify(const struct NotifyParams *notify_params)
+{
+       int result = 1;
+
+       GDBusConnection *conn = NULL;
+       GError *error = NULL;
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+       if (error) {
+               _E("g_bus_get_sync error: %s\n", error->message);
+               g_error_free(error);
+               result = 0;
+               goto end;
+       }
+
+       GVariant *data = build_message_data(notify_params);
+
+       if (data == NULL) {
+               _E("build_message error\n");
+               result = 0;
+               goto end;
+       }
+
+       g_dbus_connection_emit_signal(conn,
+                                NULL,
+                                CRASH_PATH_CRASH,
+                                CRASH_INTERFACE_CRASH,
+                                PROCESS_CRASHED,
+                                data,
+                                &error);
+
+       if (error) {
+               _E("g_dbus_connection_emit_signal error: %s\n", error->message);
+               g_error_free(error);
+               result = 0;
+               goto end;
+       }
+
+       g_dbus_connection_flush_sync(conn, NULL, &error);
+       if (error) {
+               _E("g_dbus_connection_flush_sync error: %s\n", error->message);
+               g_error_free(error);
+       }
+end:
+       if (conn != NULL)
+               g_object_unref(conn);
+
+       return result;
+}
diff --git a/src/crash-manager/dbus_notify.h b/src/crash-manager/dbus_notify.h
new file mode 100644 (file)
index 0000000..7c2f24d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ * Author: Mateusz Moscicki <m.moscicki2@partner.samsung.com>
+ */
+
+#define CRASH_BUS_NAME          "org.tizen.system.crash"
+#define CRASH_OBJECT_PATH       "/Org/Tizen/System/Crash"
+#define CRASH_INTERFACE_NAME        CRASH_BUS_NAME
+#define CRASH_PATH_CRASH            CRASH_OBJECT_PATH"/Crash"
+#define CRASH_INTERFACE_CRASH       CRASH_INTERFACE_NAME".Crash"
+#define PROCESS_CRASHED             "ProcessCrashed"
+
+struct RegInfo {
+        char *name;
+               long long int value;
+};
+
+struct NotifyParams {
+       int prstatus_fd;
+       pid_t pid;
+       pid_t tid;
+       char *cmd_name;
+       char *cmd_path;
+       char *report_path;
+       char *appid;
+       char *pkgid;
+};
+
+int send_notify(const struct NotifyParams *notify_params);