crash-manager: Always emit new style ProcessCrashedEx 75/240975/2
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Thu, 13 Aug 2020 07:24:03 +0000 (09:24 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Thu, 13 Aug 2020 09:53:15 +0000 (11:53 +0200)
ProcessCrashed signature varies between Tizen forks, so introduce
ProcessCrashedEx which does not have this problem.

Change-Id: I4cf3f2327690d6bedb6d39dc85ca96487e859acb

src/crash-manager/dbus_notify.c
tests/system/dbus_notify/dbus_notify.sh.template

index ca010e5..d802a0d 100644 (file)
@@ -40,6 +40,7 @@
 #define CRASH_PATH_CRASH        CRASH_OBJECT_PATH"/Crash"
 #define CRASH_INTERFACE_CRASH   CRASH_INTERFACE_NAME".Crash"
 #define PROCESS_CRASHED         "ProcessCrashed"
+#define PROCESS_CRASHED_EX      "ProcessCrashedEx"
 
 #define ARM_REG_LR 14
 #define ARM_REG_PC 15
@@ -211,42 +212,72 @@ static GVariant *build_message_data(const struct NotifyParams *notify_params)
        return g_variant_builder_end(&md_builder);
 }
 
-static bool send_notify(GDBusConnection *conn, const struct NotifyParams *notify_params)
+static bool send_one_signal(GDBusConnection *conn, const char *method_name, GVariant *method_data)
 {
-       int result = false;
-       GError *error = NULL;
-
-       GVariant *data = notify_params->legacy_notification
-                        ? build_legacy_message_data(notify_params)
-                        : build_message_data(notify_params);
-       if (data == NULL) {
-               _E("Error while preparing parameters");
-               goto out;
-       }
+       assert(conn);
+       assert(method_name);
+       assert(method_data);
 
+       GError *error = NULL;
        g_dbus_connection_emit_signal(conn,
                                 NULL,
                                 CRASH_PATH_CRASH,
                                 CRASH_INTERFACE_CRASH,
-                                PROCESS_CRASHED,
-                                data,
+                                method_name,
+                                method_data,
                                 &error);
        if (error) {
-               _E("Failed to emit signal: %s", error->message);
-               goto out;
+               _E("Failed to emit %s signal: %s", method_name, error->message);
+               g_error_free(error);
+               return false;
        }
 
-       g_dbus_connection_flush_sync(conn, NULL, &error);
-       if (error)
-               _E("Failed to flush connection - signal might not be delivered: %s", error->message);
+       return true;
+}
 
-       result = true;
+/* Due compatibility with various Tizen forks this programs emits following signals:
+ *   ProcessCrashedEx - using "new" signature (sssssiia{sv})
+ *   ProcessCrashed   - using either "new" or "old" signature (ssss)
+ *
+ * The signature of ProccessCrashed is controlled by UsingLegacyNotification configuration option.
+ *
+ * New programs should use ProcessCrashedEx only, or best - avoid using signals directly and
+ * depending on APIs (eg Diagnostics API).
+ */
+static bool send_signals(GDBusConnection *conn, const struct NotifyParams *notify_params)
+{
+       GVariant *data = build_message_data(notify_params);
+       if (!data) {
+               _E("Error while preparing data for " PROCESS_CRASHED_EX " signal");
+               return false;
+       }
 
-out:
-       if (error)
+       (void)g_variant_ref_sink(data);
+       send_one_signal(conn, PROCESS_CRASHED_EX, data);
+
+       GVariant *legacy = notify_params->legacy_notification
+                        ? build_legacy_message_data(notify_params)
+                        : data;
+
+       if (legacy)
+               send_one_signal(conn, PROCESS_CRASHED, legacy);
+       else
+               _W("Error while preparing data for " PROCESS_CRASHED " signal");
+
+       /* No need to free `legacy' GVariant as it's either already freed by the send call
+        * (ie. it's floating ref in legacy case) or referencing sinked ref, which is freed
+        * below.
+        */
+       g_variant_unref(data);
+
+       GError *error = NULL;
+       g_dbus_connection_flush_sync(conn, NULL, &error);
+       if (error) {
+               _E("Failed to flush connection - signal might not be delivered: %s", error->message);
                g_error_free(error);
+       }
 
-       return result;
+       return true;
 }
 
 static bool parse_cmdline(int ac, char *av[], struct NotifyParams *params)
@@ -333,7 +364,7 @@ int main(int ac, char *av[])
        if (!bus_get(&conn))
                return EXIT_FAILURE;
 
-       send_notify(conn, &params);
+       send_signals(conn, &params);
        bus_put(conn);
 
        return EXIT_SUCCESS;
index d6b0bb2..a41be8e 100644 (file)
@@ -42,22 +42,26 @@ fi
   sleep 2
   kill -6 $pid ) &
 
-TMPFILE=$(mktemp /tmp/dbus_notify.XXXXXX)
-dbus-monitor --system type=signal,path=/Org/Tizen/System/Crash/Crash,interface=org.tizen.system.crash.Crash,member=ProcessCrashed > $TMPFILE &
-monpid=$!
+TMP1=$(mktemp /tmp/dbus_notify.XXXXXX)
+TMP2=$(mktemp /tmp/dbus_notify.XXXXXX)
+dbus-monitor --system type=signal,path=/Org/Tizen/System/Crash/Crash,interface=org.tizen.system.crash.Crash,member=ProcessCrashed > $TMP1 &
+monpid1=$!
+dbus-monitor --system type=signal,path=/Org/Tizen/System/Crash/Crash,interface=org.tizen.system.crash.Crash,member=ProcessCrashedEx > $TMP2 &
+monpid2=$!
 
 cleanup()
 {
-       kill $monpid
-       rm -f $TMPFILE
+       kill $monpid1 $monpid2
+       rm -f $TMP1 $TMP2
 }
 
 trap cleanup 0
 
 sleep 3
+wait_for_app crash-manager
 
-PATTERN='path=/Org/Tizen/System/Crash/Crash; interface=org\.tizen\.system\.crash\.Crash; member=ProcessCrashed'
-for i in $(seq 1 10); do
+for TMPFILE in $TMP1 $TMP2; do
+       PATTERN="path=/Org/Tizen/System/Crash/Crash; interface=org\.tizen\.system\.crash\.Crash; member=ProcessCrashed"
        score=0
        if egrep "$PATTERN" $TMPFILE; then
                if egrep "string \"kenny" $TMPFILE; then
@@ -80,12 +84,22 @@ for i in $(seq 1 10); do
                        score=$(($score + 1))
                fi
 
+               if egrep 'ProcessCrashed\b' $TMPFILE; then
+                       has_process_crashed=yes
+               fi
+
+               if egrep 'ProcessCrashedEx\b' $TMPFILE; then
+                       has_process_crashed_ex=yes
+               fi
+
                if [ $score -eq 5 ]; then
-                       exit_ok
+                       continue
                fi
        fi
 
-       sleep 1
+       fail "dbus signal does not match"
 done
 
-fail "dbus signal does not match"
+[ x$has_process_crashed = xyes ] && [ x$has_process_crashed_ex = xyes ] || fail "necessary signals not matched (ProcessCrashed and ProcessCrashedEx)"
+
+exit_ok