crash-pipe: Add utility to process core sent to stdin 43/60043/3
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Mon, 22 Feb 2016 17:11:30 +0000 (18:11 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Mon, 29 Feb 2016 12:13:56 +0000 (13:13 +0100)
This is going to be used as systemd-coredump replacement.

Change-Id: Ib7074ba5e10990d8487b1693a8c92431cdee6964

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

index 2e1fb00..9e407b2 100644 (file)
@@ -5,5 +5,6 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 
 # Sub modules
 ADD_SUBDIRECTORY(src/crash-manager)
+ADD_SUBDIRECTORY(src/crash-pipe)
 ADD_SUBDIRECTORY(src/dump_systemstate)
 
index 9fc9b36..4631c8d 100644 (file)
@@ -35,7 +35,9 @@ export CFLAGS+=" -Werror"
           -DTZ_SYS_BIN=%{TZ_SYS_BIN} \
           -DUNIT_DIR=%{_unitdir} \
           -DCRASH_PATH=%{crash_path} \
-          -DCRASH_TEMP=%{crash_temp}
+          -DCRASH_TEMP=%{crash_temp} \
+          -DCRASH_PIPE_PATH=%{_libexecdir}/crash-pipe
+
 make %{?jobs:-j%jobs}
 
 %install
@@ -57,6 +59,7 @@ mkdir -p %{buildroot}%{crash_temp}
 %attr(0755,system,system) %{_bindir}/dump_systemstate
 %{_bindir}/crash-manager.sh
 %{_bindir}/crash-init.sh
+%{_libexecdir}/crash-pipe
 %{_prefix}/lib/sysctl.d/99-crash-manager.conf
 %{_unitdir}/crash-init.service
 %{_unitdir}/sysinit.target.wants/crash-init.service
diff --git a/src/crash-pipe/CMakeLists.txt b/src/crash-pipe/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7405769
--- /dev/null
@@ -0,0 +1,5 @@
+set(CRASH_PIPE_BIN "crash-pipe")
+set(CRASH_PIPE_SRCS crash-pipe.c)
+
+add_executable(${CRASH_PIPE_BIN} ${CRASH_PIPE_SRCS})
+install(TARGETS ${CRASH_PIPE_BIN} DESTINATION libexec)
diff --git a/src/crash-pipe/crash-pipe.c b/src/crash-pipe/crash-pipe.c
new file mode 100644 (file)
index 0000000..21bec53
--- /dev/null
@@ -0,0 +1,145 @@
+/* crash-pipe: handle core file passed from stdin
+ *
+ * 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: Karol Lewandowski <k.lewandowsk@samsung.com>
+ */
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <syslog.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#define NELEMS(arr) (sizeof(arr)/sizeof(arr[0]))
+
+enum {
+     OPT_HELP,
+     OPT_REPORT,
+     OPT_SAVE_CORE,
+};
+
+const struct option opts[] = {
+     { "help", no_argument, 0, OPT_HELP },
+     { "report", no_argument, 0, OPT_REPORT },
+     { "save-core", required_argument, 0, OPT_SAVE_CORE },
+     { 0, 0, 0, 0 }
+};
+
+static char *argv0 = "";
+
+static void usage(void)
+{
+     fprintf(stderr, "usage: %s [--help] [--save-core FILE_NAME] [--report] PID UID GID SIGNAL DUMPTIME EXE\n",
+            argv0);
+}
+
+static void report(int argc, char *argv[])
+{
+     const char *pidstr = argv[0];
+
+
+     printf("Process crash report: %s\n"
+           "\tpid: %s\n"
+           "\tuid: %s\n"
+           "\tgid: %s\n"
+           "\tsignal: %s\n"
+           "\ttimestamp of crash: %s\n",
+           argv[5], pidstr, argv[1], argv[2], argv[3], argv[4]);
+
+}
+
+static int save_core(const char *core_path)
+{
+     int fd;
+     static char buf[4096];
+     int readb, remaining;
+
+     fd = open(core_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+     if (fd == -1) {
+         syslog(LOG_ERR, "crash-pipe: Unable to save core file to %s: %s\n",
+                core_path, strerror(errno));
+         return -1;
+     }
+
+     while ((readb = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
+         int n;
+
+         for (n = 0, remaining = readb ; remaining > 0; remaining -= n) {
+              n = write(fd, buf, remaining);
+              if (n == -1) {
+                   syslog(LOG_ERR, "crash-pipe: Error while saving core file %s: %s. Removing core.\n",
+                          core_path, strerror(errno));
+                   (void)unlink(core_path); // XXX check errors here too
+                   return 0;
+              }
+         }
+     }
+
+     close(fd);
+
+     return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+     int c;
+     int opt_report = 0;
+     char *opt_save_core = NULL;
+     _Bool ret = 1;
+
+     prctl(PR_SET_DUMPABLE, 0);
+
+     argv0 = argv[0];
+
+
+     while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1) {
+
+         if (c == OPT_HELP) {
+              usage();
+              exit(EXIT_SUCCESS);
+         }
+         else if (c == OPT_REPORT) {
+              opt_report = 1;
+         }
+         else if (c == OPT_SAVE_CORE) {
+              opt_save_core = strdup(optarg);
+              if (!opt_save_core) {
+                   syslog(LOG_CRIT, "Out of memory. Exiting.");
+                   exit(EXIT_FAILURE);
+              }
+         }
+     }
+
+     argc -= optind;
+     argv += optind;
+
+     if (opt_report)
+         report(argc, argv);
+
+     if (opt_save_core)
+         ret = save_core(opt_save_core);
+
+     return ret >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}