Add AUL unix signal handler 20/221620/8
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 6 Jan 2020 08:54:28 +0000 (17:54 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 6 Jan 2020 22:59:57 +0000 (07:59 +0900)
To detect segmentation fault, AUL adds signal handlers.
While getting the signal, AUL deletes the AUL socket path.

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/221620/
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/221624/

Change-Id: I69ad0ce2b5b708e5183cfb1f4d3e72885bb5cad0
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
CMakeLists.txt
include/aul_cmd.h
include/aul_key.h
include/aul_unix_signal.h [new file with mode: 0644]
packaging/aul.spec
src/aul_cmd.c
src/aul_launch.c
src/aul_unix_signal.c [new file with mode: 0644]

index e50e78c..4b66e23 100755 (executable)
@@ -38,6 +38,11 @@ FOREACH(APP_LAUNCHER_FLAGS ${APP_LAUNCHER_DEPS_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${APP_LAUNCHER_FLAGS}")
 ENDFOREACH(APP_LAUNCHER_FLAGS)
 
+IF(_TIZEN_FEATURE_DEBUG_MODE)
+MESSAGE(STATUS "DEBUG MODE")
+ADD_DEFINITIONS(-DTIZEN_FEATURE_DEBUG_MODE)
+ENDIF(_TIZEN_FEATURE_DEBUG_MODE)
+
 # Compiler flags
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/legacy)
@@ -55,7 +60,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 
 # aul
 add_library(aul SHARED ${SOURCES})
-TARGET_LINK_LIBRARIES(aul ${libpkgs_LDFLAGS})
+TARGET_LINK_LIBRARIES(aul ${libpkgs_LDFLAGS} "-ldl")
 SET_TARGET_PROPERTIES(aul PROPERTIES SOVERSION ${MAJORVER})
 SET_TARGET_PROPERTIES(aul PROPERTIES VERSION ${FULLVER})
 INSTALL(TARGETS aul DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
index 0a7d201..f877cec 100755 (executable)
@@ -173,6 +173,7 @@ enum app_cmd {
        APP_IS_RUNNING_V2 = 134,
        ANR_NOTIFY = 135,
        APP_GET_RUNNING_CONTEXT = 136,
+       APP_NOTIFY_SIGNAL = 137,
 
        APP_CMD_MAX
 };
index d56dee5..1d1ec01 100644 (file)
  * @since_tizen 5.5
  */
 #define AUL_K_LAUNCHER_SERVICE_SERIAL   "__K_LAUNCHER_SERVICE_SERIAL__"
+
+/**
+ * @brief Definition for AUL: The signal number.
+ * @since_tizen 5.5
+ */
+#define AUL_K_SIGNAL                    "__AUL_SIGNAL__"
diff --git a/include/aul_unix_signal.h b/include/aul_unix_signal.h
new file mode 100644 (file)
index 0000000..039e9b3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __AUL_UNIX_SIGNAL_H__
+#define __AUL_UNIX_SIGNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Called when the signal is occurred.
+ * @since_tizen 5.5
+ *
+ * @param[in]   signum          The signal number
+ * @param[in]   user_data       The user data passed from the callback registration function
+ *
+ * @see aul_unix_signal_set_event_cb()
+ */
+typedef void (*aul_unix_signal_cb)(int signum, void *user_data);
+
+/**
+ * @brief Initializes AUL unix signal handler.
+ * @since_tizen 5.5
+ *
+ * @return      @c 0 on success,
+ *              otherwise a negative error value.
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_unix_signal_init(void);
+
+/**
+ * @brief Finalizes AUL unix signal handler.
+ * @since_tizen 5.5
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+void aul_unix_signal_fini(void);
+
+/**
+ * @brief Sets the event callback of AUL unix signal.
+ * @since_tizen 5.5
+ *
+ * @param[in]   callback        The callback function to be called when the signal is occurred
+ * @param[in]   user_data       The user data to be passed to the callback function
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_unix_signal_set_event_cb(aul_unix_signal_cb callback, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AUL_UNIX_SIGNAL_H__ */
index ed65316..2be609c 100755 (executable)
@@ -62,6 +62,12 @@ Application utility library (test tools)
 %define tizen_feature_prelink 0
 %endif
 
+%if "%{?tizen_build_devel_mode}" == "1"
+%define tizen_debug_mode 1
+%else
+%define tizen_debug_mode 0
+%endif
+
 %prep
 %setup -q
 sed -i 's|TZ_SYS_DB|%{TZ_SYS_DB}|g' %{SOURCE1001}
@@ -76,10 +82,15 @@ CFLAGS="%{optflags} -D__emul__"; export CFLAGS
 _TIZEN_FEATURE_PRELINK=ON
 %endif
 
+%if 0%{?tizen_debug_mode}
+_TIZEN_FEATURE_DEBUG_MODE=ON
+%endif
+
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake -DFULLVER=%{version} \
        -DMAJORVER=${MAJORVER} \
        -D_TIZEN_FEATURE_PRELINK:BOOL=${_TIZEN_FEATURE_PRELINK} \
+       -D_TIZEN_FEATURE_DEBUG_MODE:BOOL=${_TIZEN_FEATURE_DEBUG_MODE} \
        .
 
 %__make %{?_smp_mflags}
index d33be74..93da427 100755 (executable)
@@ -298,6 +298,8 @@ API const char *aul_cmd_convert_to_string(int cmd)
                return "ANR_NOTIFY";
        case APP_GET_RUNNING_CONTEXT:
                return "APP_GET_RUNNING_CONTEXT";
+       case APP_NOTIFY_SIGNAL:
+               return "APP_NOTIFY_SIGNAL";
        default:
                return "CUSTOM_COMMAND";
        }
index 6a3924e..a926d57 100644 (file)
@@ -38,6 +38,7 @@
 #include "aul_watch_control_internal.h"
 #include "aul_worker.h"
 #include "aul_watchdog.h"
+#include "aul_unix_signal.h"
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 
@@ -389,6 +390,31 @@ static bool __worker_io_job_cb(int fd, void *user_data)
        return true;
 }
 
+static void __aul_signal_handler(int signum, void *user_data)
+{
+       char buf[12];
+       bundle *b;
+       int ret;
+
+       aul_sock_destroy_server(-1);
+
+       b = bundle_create();
+       if (!b) {
+               _E("Failed to create bundle");
+               return;
+       }
+
+       snprintf(buf, sizeof(buf), "%d", signum);
+       bundle_add(b, AUL_K_SIGNAL, buf);
+
+       ret = aul_sock_send_bundle(AUL_UTIL_PID, getuid(),
+                       APP_NOTIFY_SIGNAL, b, AUL_SOCK_NOREPLY);
+       if (ret != AUL_R_OK)
+               _E("Failed to notify signal. error(%d)", ret);
+
+       bundle_free(b);
+}
+
 static void __finalize_context(void)
 {
        if (__context.worker) {
@@ -396,6 +422,8 @@ static void __finalize_context(void)
                __context.worker = NULL;
        }
 
+       aul_unix_signal_fini();
+
        __context.initialized = false;
 }
 
@@ -410,6 +438,12 @@ static int __initialize_context(void)
                return fd;
        }
 
+       ret = aul_unix_signal_init();
+       if (ret < 0)
+               return AUL_R_ERROR;
+
+       aul_unix_signal_set_event_cb(__aul_signal_handler, NULL);
+
        __context.worker = aul_worker_create("aul+");
        if (!__context.worker) {
                __finalize_context();
diff --git a/src/aul_unix_signal.c b/src/aul_unix_signal.c
new file mode 100644 (file)
index 0000000..670a34f
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <signal.h>
+#include <stdio.h>
+
+#include "aul_unix_signal.h"
+#include "aul_util.h"
+
+#ifdef TIZEN_FEATURE_DEBUG_MODE
+#include <dlfcn.h>
+#include <execinfo.h>
+
+#define BT_BUF_SIZE 128
+
+#define PRINT_BACKTRACE() do {                                                 \
+        int i;                                                                 \
+        int nptrs;                                                             \
+        void *buffer[BT_BUF_SIZE];                                             \
+        char **strings;                                                        \
+        Dl_info info;                                                          \
+                                                                               \
+        nptrs = backtrace(buffer, BT_BUF_SIZE);                                \
+        strings = backtrace_symbols(buffer, nptrs);                            \
+        if (!strings) {                                                        \
+                dlog_print(DLOG_ERROR, "AUL_BACKTRACE", "backtrace_symbols");  \
+                break;                                                         \
+        }                                                                      \
+                                                                               \
+        i = (nptrs > 2) ? 2 : 0;                                               \
+        dlog_print(DLOG_ERROR, "AUL_BACKTRACE",                                \
+                        "%s backtrace() returns %d address",                   \
+                        strings[i], nptrs - i);                                \
+                                                                               \
+        for (i = 0; i < nptrs; i++) {                                          \
+                dladdr(buffer[i], &info);                                      \
+                if (i > 1) {                                                   \
+                        dlog_print(DLOG_ERROR, "AUL_BACKTRACE",                \
+                                        "[%2d] %s %s\n",                       \
+                                        i - 2,                                 \
+                                        info.dli_sname ? info.dli_sname : "?", \
+                                        strings[i]);                           \
+                }                                                              \
+        }                                                                      \
+} while (0)
+#endif /* TIZEN_FEATURE_DEBUG_MODE */
+
+typedef enum {
+       AUL_SIGHUP,
+       AUL_SIGINT,
+       AUL_SIGQUIT,
+       AUL_SIGILL,
+       AUL_SIGABRT,
+       AUL_SIGFPE,
+       AUL_SIGBUS,
+       AUL_SIGSEGV,
+       AUL_SIGALRM,
+       AUL_SIGTERM,
+       AUL_SIGXCPU,
+       AUL_SIGXFSZ,
+       AUL_SIGSYS,
+       AUL_SIGMAX,
+} aul_signo_e;
+
+static aul_unix_signal_cb __callback;
+static void *__user_data;
+static struct sigaction __old_action[AUL_SIGMAX];
+
+static int __get_unix_signo(aul_signo_e aul_signo)
+{
+       static int unix_signo[AUL_SIGMAX] = {
+               [AUL_SIGHUP] = SIGHUP,
+               [AUL_SIGINT] = SIGINT,
+               [AUL_SIGQUIT] = SIGQUIT,
+               [AUL_SIGILL] = SIGILL,
+               [AUL_SIGABRT] = SIGABRT,
+               [AUL_SIGFPE] = SIGFPE,
+               [AUL_SIGBUS] = SIGBUS,
+               [AUL_SIGSEGV] = SIGSEGV,
+               [AUL_SIGALRM] = SIGALRM,
+               [AUL_SIGTERM] = SIGTERM,
+               [AUL_SIGXCPU] = SIGXCPU,
+               [AUL_SIGXFSZ] = SIGXFSZ,
+               [AUL_SIGSYS] = SIGSYS,
+       };
+
+       if (aul_signo >= AUL_SIGMAX)
+               return -1;
+
+       return unix_signo[aul_signo];
+}
+
+static int __get_aul_signo(int signo)
+{
+       int i;
+
+       for (i = 0; i < AUL_SIGMAX; i++)
+               if (__get_unix_signo(i) == signo)
+                       return i;
+
+       return -1;
+}
+
+static const char *__get_aul_signo_string(aul_signo_e aul_signo)
+{
+       static const char *aul_signo_string[] = {
+               [AUL_SIGHUP] = "SIGHUP",
+               [AUL_SIGINT] = "SIGINT",
+               [AUL_SIGQUIT] = "SIGQUIT",
+               [AUL_SIGILL] = "SIGILL",
+               [AUL_SIGABRT] = "SIGABRT",
+               [AUL_SIGFPE] = "SIGFPE",
+               [AUL_SIGBUS] = "SIGBUS",
+               [AUL_SIGSEGV] = "SIGSEGV",
+               [AUL_SIGALRM] = "SIGALRM",
+               [AUL_SIGTERM] = "SIGTERM",
+               [AUL_SIGXCPU] = "SIGXCPU",
+               [AUL_SIGXFSZ] = "SIGXFSZ",
+               [AUL_SIGSYS] = "SIGSYS",
+       };
+
+       if (aul_signo >= AUL_SIGMAX)
+               return "Unknown";
+
+       return aul_signo_string[aul_signo];
+}
+
+static void __aul_unix_signal_handler(int signo, siginfo_t *info, void *arg)
+{
+       int aul_signo;
+
+       _E("[__SIGNAL__] signal: %d(%s)",
+                       signo, __get_aul_signo_string(__get_aul_signo(signo)));
+
+#ifdef TIZEN_FEATURE_DEBUG_MODE
+       PRINT_BACKTRACE();
+#endif /* TIZEN_FEATURE_DEBUG_MODE */
+
+       if (__callback)
+               __callback(signo, __user_data);
+
+       aul_signo = __get_aul_signo(signo);
+       if (aul_signo != -1) {
+               sigaction(signo, &__old_action[aul_signo], NULL);
+               raise(signo);
+       }
+}
+
+int aul_unix_signal_set_event_cb(aul_unix_signal_cb callback,
+               void *user_data)
+{
+       __callback = callback;
+       __user_data = user_data;
+
+       return 0;
+}
+
+int aul_unix_signal_init(void)
+{
+       struct sigaction action = { 0, };
+       int signo;
+       int i;
+
+       sigemptyset(&action.sa_mask);
+       action.sa_sigaction = __aul_unix_signal_handler;
+       action.sa_flags = SA_RESTART | SA_SIGINFO;
+
+       for (i = 0; i < AUL_SIGMAX; i++) {
+               signo = __get_unix_signo(i);
+               if (signo != -1)
+                       sigaction(signo, &action, &__old_action[i]);
+       }
+
+       return 0;
+}
+
+void aul_unix_signal_fini(void)
+{
+       int signo;
+       int i;
+
+       aul_unix_signal_set_event_cb(NULL, NULL);
+
+       for (i = 0; i < AUL_SIGMAX; i++) {
+               signo = __get_unix_signo(i);
+               if (signo != -1)
+                       sigaction(signo, &__old_action[i], NULL);
+       }
+}