From 39988d1118fca6a9cdd952cfbbcbb07639dffa4b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 5 Nov 2016 22:21:17 -0400 Subject: HACKING: mkosi is now packaged for Fedora Also dnf requires sudo. --- HACKING | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HACKING b/HACKING index 3ee1c7e340..0d1a93e211 100644 --- a/HACKING +++ b/HACKING @@ -51,12 +51,14 @@ systemd's build dependencies: Putting this all together, here's a series of commands for preparing a patch for systemd (this example is for Fedora): + $ sudo dnf builddep systemd # install build dependencies + $ sudo dnf install mkosi # install tool to quickly build images $ git clone https://github.com/systemd/systemd.git $ cd systemd $ vim src/core/main.c # or wherever you'd like to make your changes - $ dnf builddep systemd # install build dependencies $ ./autogen.sh c # configure the source tree $ make -j `nproc` # build it locally, see if everything compiles fine + $ make -j `nproc` check # run some simple regression tests $ sudo mkosi # build a test image $ sudo systemd-nspawn -bi image.raw # boot up the test image $ git add -p # interactively put together your patch -- cgit v1.2.3-54-g00ecf From 9aa820231414baa28e6bf02a033932cb69ff6b8b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 30 Oct 2016 17:37:38 -0400 Subject: coredump: split out metadata gathering to a separate function In preparation for subsequenct changes... Various stack allocations are changed to use the heap. This might be minimally slower, but probably doesn't matter. The upside is that we will now properly free all memory that is allocated. --- src/coredump/coredump.c | 270 ++++++++++++++++++++---------------------------- 1 file changed, 112 insertions(+), 158 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 1f6fb5de1e..d5b638d7ec 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -1025,45 +1025,43 @@ static int process_special_crash(const char *context[], int input_fd) { return 0; } -static int process_kernel(int argc, char* argv[]) { +static char* set_iovec_field(struct iovec iovec[27], size_t *n_iovec, const char *field, const char *value) { + char *x; - /* The small core field we allocate on the stack, to keep things simple */ - char - *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL, - *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL, - *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL, - *core_user_unit = NULL, *core_slice = NULL, *core_timestamp = NULL, *core_rlimit = NULL; + x = strappend(field, value); + if (x) + IOVEC_SET_STRING(iovec[(*n_iovec)++], x); + return x; +} - /* The larger ones we allocate on the heap */ - _cleanup_free_ char - *core_owner_uid = NULL, *core_open_fds = NULL, *core_proc_status = NULL, - *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL, - *core_proc_mountinfo = NULL, *core_container_cmdline = NULL; +static char* set_iovec_field_free(struct iovec iovec[27], size_t *n_iovec, const char *field, char *value) { + char *x; + + x = set_iovec_field(iovec, n_iovec, field, value); + free(value); + return x; +} + +static int gather_pid_metadata( + const char *context[_CONTEXT_MAX], + char **comm_fallback, + struct iovec iovec[27], size_t *n_iovec) { _cleanup_free_ char *exe = NULL, *comm = NULL; - const char *context[_CONTEXT_MAX]; - bool proc_self_root_is_slash; - struct iovec iovec[27]; - size_t n_iovec = 0; uid_t owner_uid; - const char *p; pid_t pid; char *t; + const char *p; int r; - if (argc < CONTEXT_COMM + 1) { - log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); - return -EINVAL; - } - - r = parse_pid(argv[CONTEXT_PID + 1], &pid); + r = parse_pid(context[CONTEXT_PID], &pid); if (r < 0) return log_error_errno(r, "Failed to parse PID."); r = get_process_comm(pid, &comm); if (r < 0) { log_warning_errno(r, "Failed to get COMM, falling back to the command line: %m"); - comm = strv_join(argv + CONTEXT_COMM + 1, " "); + comm = strv_join(comm_fallback, " "); if (!comm) return log_oom(); } @@ -1072,15 +1070,6 @@ static int process_kernel(int argc, char* argv[]) { if (r < 0) log_warning_errno(r, "Failed to get EXE, ignoring: %m"); - context[CONTEXT_PID] = argv[CONTEXT_PID + 1]; - context[CONTEXT_UID] = argv[CONTEXT_UID + 1]; - context[CONTEXT_GID] = argv[CONTEXT_GID + 1]; - context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 1]; - context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1]; - context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1]; - context[CONTEXT_COMM] = comm; - context[CONTEXT_EXE] = exe; - if (cg_pid_get_unit(pid, &t) >= 0) { /* If this is PID 1 disable coredump collection, we'll unlikely be able to process it later on. */ @@ -1096,170 +1085,129 @@ static int process_kernel(int argc, char* argv[]) { return process_special_crash(context, STDIN_FILENO); } - core_unit = strjoina("COREDUMP_UNIT=", t); - free(t); - - IOVEC_SET_STRING(iovec[n_iovec++], core_unit); + set_iovec_field_free(iovec, n_iovec, "COREDUMP_UNIT=", t); } /* OK, now we know it's not the journal, hence we can make use of it now. */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_open(); - if (cg_pid_get_user_unit(pid, &t) >= 0) { - core_user_unit = strjoina("COREDUMP_USER_UNIT=", t); - free(t); + if (cg_pid_get_user_unit(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_USER_UNIT=", t); - IOVEC_SET_STRING(iovec[n_iovec++], core_user_unit); - } + /* The next few are mandatory */ + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID])) + return log_oom(); - core_pid = strjoina("COREDUMP_PID=", context[CONTEXT_PID]); - IOVEC_SET_STRING(iovec[n_iovec++], core_pid); + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID])) + return log_oom(); - core_uid = strjoina("COREDUMP_UID=", context[CONTEXT_UID]); - IOVEC_SET_STRING(iovec[n_iovec++], core_uid); + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID])) + return log_oom(); - core_gid = strjoina("COREDUMP_GID=", context[CONTEXT_GID]); - IOVEC_SET_STRING(iovec[n_iovec++], core_gid); + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL])) + return log_oom(); - core_signal = strjoina("COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]); - IOVEC_SET_STRING(iovec[n_iovec++], core_signal); + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT])) + return log_oom(); - core_rlimit = strjoina("COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]); - IOVEC_SET_STRING(iovec[n_iovec++], core_rlimit); + if (!set_iovec_field(iovec, n_iovec, "COREDUMP_COMM=", comm)) + return log_oom(); - if (sd_pid_get_session(pid, &t) >= 0) { - core_session = strjoina("COREDUMP_SESSION=", t); - free(t); + if (exe && + !set_iovec_field(iovec, n_iovec, "COREDUMP_EXE=", exe)) + return log_oom(); - IOVEC_SET_STRING(iovec[n_iovec++], core_session); - } + if (sd_pid_get_session(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_SESSION=", t); if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) { - r = asprintf(&core_owner_uid, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid); + r = asprintf(&t, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid); if (r > 0) - IOVEC_SET_STRING(iovec[n_iovec++], core_owner_uid); - } - - if (sd_pid_get_slice(pid, &t) >= 0) { - core_slice = strjoina("COREDUMP_SLICE=", t); - free(t); - - IOVEC_SET_STRING(iovec[n_iovec++], core_slice); - } - - if (comm) { - core_comm = strjoina("COREDUMP_COMM=", comm); - IOVEC_SET_STRING(iovec[n_iovec++], core_comm); - } - - if (exe) { - core_exe = strjoina("COREDUMP_EXE=", exe); - IOVEC_SET_STRING(iovec[n_iovec++], core_exe); + IOVEC_SET_STRING(iovec[(*n_iovec)++], t); } - if (get_process_cmdline(pid, 0, false, &t) >= 0) { - core_cmdline = strjoina("COREDUMP_CMDLINE=", t); - free(t); + if (sd_pid_get_slice(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_SLICE=", t); - IOVEC_SET_STRING(iovec[n_iovec++], core_cmdline); - } - - if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) { - core_cgroup = strjoina("COREDUMP_CGROUP=", t); - free(t); + if (get_process_cmdline(pid, 0, false, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_CMDLINE=", t); - IOVEC_SET_STRING(iovec[n_iovec++], core_cgroup); - } + if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_CGROUP=", t); - if (compose_open_fds(pid, &t) >= 0) { - core_open_fds = strappend("COREDUMP_OPEN_FDS=", t); - free(t); - - if (core_open_fds) - IOVEC_SET_STRING(iovec[n_iovec++], core_open_fds); - } + if (compose_open_fds(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_OPEN_FDS=", t); p = procfs_file_alloca(pid, "status"); - if (read_full_file(p, &t, NULL) >= 0) { - core_proc_status = strappend("COREDUMP_PROC_STATUS=", t); - free(t); - - if (core_proc_status) - IOVEC_SET_STRING(iovec[n_iovec++], core_proc_status); - } + if (read_full_file(p, &t, NULL) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_STATUS=", t); p = procfs_file_alloca(pid, "maps"); - if (read_full_file(p, &t, NULL) >= 0) { - core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t); - free(t); - - if (core_proc_maps) - IOVEC_SET_STRING(iovec[n_iovec++], core_proc_maps); - } + if (read_full_file(p, &t, NULL) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MAPS=", t); p = procfs_file_alloca(pid, "limits"); - if (read_full_file(p, &t, NULL) >= 0) { - core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t); - free(t); - - if (core_proc_limits) - IOVEC_SET_STRING(iovec[n_iovec++], core_proc_limits); - } + if (read_full_file(p, &t, NULL) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_LIMITS=", t); p = procfs_file_alloca(pid, "cgroup"); - if (read_full_file(p, &t, NULL) >=0) { - core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t); - free(t); - - if (core_proc_cgroup) - IOVEC_SET_STRING(iovec[n_iovec++], core_proc_cgroup); - } + if (read_full_file(p, &t, NULL) >=0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_CGROUP=", t); p = procfs_file_alloca(pid, "mountinfo"); - if (read_full_file(p, &t, NULL) >=0) { - core_proc_mountinfo = strappend("COREDUMP_PROC_MOUNTINFO=", t); - free(t); + if (read_full_file(p, &t, NULL) >=0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MOUNTINFO=", t); - if (core_proc_mountinfo) - IOVEC_SET_STRING(iovec[n_iovec++], core_proc_mountinfo); - } - - if (get_process_cwd(pid, &t) >= 0) { - core_cwd = strjoina("COREDUMP_CWD=", t); - free(t); - - IOVEC_SET_STRING(iovec[n_iovec++], core_cwd); - } + if (get_process_cwd(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_CWD=", t); if (get_process_root(pid, &t) >= 0) { - core_root = strjoina("COREDUMP_ROOT=", t); + bool proc_self_root_is_slash; + + proc_self_root_is_slash = strcmp(t, "/") == 0; - IOVEC_SET_STRING(iovec[n_iovec++], core_root); + set_iovec_field_free(iovec, n_iovec, "COREDUMP_ROOT=", t); /* If the process' root is "/", then there is a chance it has * mounted own root and hence being containerized. */ - proc_self_root_is_slash = strcmp(t, "/") == 0; - free(t); - if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0) { - core_container_cmdline = strappend("COREDUMP_CONTAINER_CMDLINE=", t); - free(t); - - if (core_container_cmdline) - IOVEC_SET_STRING(iovec[n_iovec++], core_container_cmdline); - } + if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_CONTAINER_CMDLINE=", t); } - if (get_process_environ(pid, &t) >= 0) { - core_environ = strappend("COREDUMP_ENVIRON=", t); - free(t); + if (get_process_environ(pid, &t) >= 0) + set_iovec_field_free(iovec, n_iovec, "COREDUMP_ENVIRON=", t); + + t = strjoin("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000", NULL); + if (t) + IOVEC_SET_STRING(iovec[(*n_iovec)++], t); + + return 0; +} - if (core_environ) - IOVEC_SET_STRING(iovec[n_iovec++], core_environ); +static int process_kernel(int argc, char* argv[]) { + + const char *context[_CONTEXT_MAX]; + struct iovec iovec[27]; + size_t n_iovec = 0, i, n_to_free; + int r; + + if (argc < CONTEXT_COMM + 1) { + log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); + return -EINVAL; } - core_timestamp = strjoina("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000"); - IOVEC_SET_STRING(iovec[n_iovec++], core_timestamp); + context[CONTEXT_PID] = argv[CONTEXT_PID + 1]; + context[CONTEXT_UID] = argv[CONTEXT_UID + 1]; + context[CONTEXT_GID] = argv[CONTEXT_GID + 1]; + context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 1]; + context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1]; + context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1]; + + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, iovec, &n_iovec); + if (r < 0) + goto finish; + n_to_free = n_iovec; IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); @@ -1268,14 +1216,20 @@ static int process_kernel(int argc, char* argv[]) { assert(n_iovec <= ELEMENTSOF(iovec)); - return send_iovec(iovec, n_iovec, STDIN_FILENO); + r = send_iovec(iovec, n_iovec, STDIN_FILENO); + + finish: + for (i = 0; i < n_to_free; i++) + free(iovec[i].iov_base); + + return r; } int main(int argc, char *argv[]) { int r; - /* First, log to a safe place, since we don't know what crashed and it might be journald which we'd rather not - * log to then. */ + /* First, log to a safe place, since we don't know what crashed and it might + * be journald which we'd rather not log to then. */ log_set_target(LOG_TARGET_KMSG); log_open(); @@ -1295,8 +1249,8 @@ int main(int argc, char *argv[]) { goto finish; } - /* If we got an fd passed, we are running in coredumpd mode. Otherwise we are invoked from the kernel as - * coredump handler */ + /* If we got an fd passed, we are running in coredumpd mode. Otherwise we + * are invoked from the kernel as coredump handler. */ if (r == 0) r = process_kernel(argc, argv); else if (r == 1) -- cgit v1.2.3-54-g00ecf From 988e89ee3b95c3ab2f47bc95c4eef0325e4636b7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 30 Oct 2016 22:42:44 -0400 Subject: coredump: implement logging of external backtraces with --backtrace This is useful for example for Python progams. By installing a python sys.execepthook we can store the backtrace in the journal. We gather the backtrace in the python process, and call systemd-coredump to attach additional fields (COREDUMP_COMM, COREDUMP_EXE, COREDUMP_UNIT, COREDUMP_USER_UNIT, COREDUMP_OWNER_UID, COREDUMP_SLICE, COREDUMP_CMDLINE, COREDUMP_CGROUP, COREDUMP_OPEN_FDS, COREDUMP_PROC_STATUS, COREDUMP_PROC_MAPS, COREDUMP_PROC_LIMITS, COREDUMP_PROC_MOUNTINFO, COREDUMP_CWD, COREDUMP_ROOT, COREDUMP_ENVIRON, COREDUMP_CONTAINER_CMDLINE). This could also be done in the python process, but doing this in systemd-coredump saves quite a bit of duplicate work and unifies the handling of various tricky fields like COREDUMP_CONTAINER_CMDLINE in one place. (Of course this applies to any other language which does not dump cores but wants to log a traceback, e.g. ruby.) journal entry: _TRANSPORT=journal _UID=1002 _GID=1002 _CAP_EFFECTIVE=0 _AUDIT_LOGINUID=1002 _SYSTEMD_OWNER_UID=1002 _SYSTEMD_SLICE=user-1002.slice _SYSTEMD_USER_SLICE=-.slice _SELINUX_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 _BOOT_ID=1531fd22ec84429e85ae888b12fadb91 _MACHINE_ID=519a16632fbd4c71966ce9305b360c9c _HOSTNAME=laptop _AUDIT_SESSION=1 _SYSTEMD_UNIT=user@1002.service _SYSTEMD_INVOCATION_ID=3c4238d790a44aca9576ecdb2c7576d3 COREDUMP_UNIT=user@1002.service COREDUMP_USER_UNIT=gnome-terminal-server.service COREDUMP_UID=1002 COREDUMP_GID=1002 COREDUMP_OWNER_UID=1002 COREDUMP_SLICE=user-1002.slice COREDUMP_CGROUP=/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service COREDUMP_PROC_LIMITS=Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size unlimited unlimited bytes Max resident set unlimited unlimited bytes Max processes 15413 15413 processes Max open files 4096 4096 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 15413 15413 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us COREDUMP_PROC_CGROUP=1:name=systemd:/ 0::/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service COREDUMP_PROC_MOUNTINFO=17 39 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel 18 39 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw 19 39 0:6 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=1972980k,nr_inodes=493245,mode=755 20 17 0:18 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw 21 19 0:19 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel 22 19 0:20 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000 23 39 0:21 / /run rw,nosuid,nodev shared:12 - tmpfs tmpfs rw,seclabel,mode=755 24 17 0:22 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:8 - cgroup2 cgroup rw 25 17 0:23 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:9 - pstore pstore rw,seclabel 36 17 0:24 / /sys/kernel/config rw,relatime shared:10 - configfs configfs rw 39 0 0:26 /root / rw,relatime shared:1 - btrfs /dev/mapper/fedora-root2 rw,seclabel,ssd,space_cache,subvolid=257,subvol=/root 26 17 0:16 / /sys/fs/selinux rw,relatime shared:11 - selinuxfs selinuxfs rw 27 19 0:15 / /dev/mqueue rw,relatime shared:13 - mqueue mqueue rw,seclabel 28 18 0:30 / /proc/sys/fs/binfmt_misc rw,relatime shared:14 - autofs systemd-1 rw,fd=35,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=13663 29 17 0:7 / /sys/kernel/debug rw,relatime shared:15 - debugfs debugfs rw,seclabel 30 19 0:31 / /dev/hugepages rw,relatime shared:16 - hugetlbfs hugetlbfs rw,seclabel 31 18 0:32 / /proc/fs/nfsd rw,relatime shared:17 - nfsd nfsd rw 32 28 0:33 / /proc/sys/fs/binfmt_misc rw,relatime shared:18 - binfmt_misc binfmt_misc rw 57 39 0:34 / /tmp rw,relatime shared:19 - tmpfs none rw,seclabel 61 57 0:35 / /tmp/test rw,relatime shared:20 - autofs systemd-1 rw,fd=48,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=18251 59 39 8:1 / /boot rw,relatime shared:21 - ext4 /dev/sda1 rw,seclabel,data=ordered 60 39 253:2 / /home rw,relatime shared:22 - ext4 /dev/mapper/fedora-home rw,seclabel,data=ordered 65 39 0:37 / /var/lib/nfs/rpc_pipefs rw,relatime shared:23 - rpc_pipefs sunrpc rw 136 23 0:39 / /run/user/1002 rw,nosuid,nodev,relatime shared:91 - tmpfs tmpfs rw,seclabel,size=397432k,mode=700,uid=1002,gid=1002 211 23 0:41 / /run/user/42 rw,nosuid,nodev,relatime shared:163 - tmpfs tmpfs rw,seclabel,size=397432k,mode=700,uid=42,gid=42 329 136 0:44 / /run/user/1002/gvfs rw,nosuid,nodev,relatime shared:277 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1002,group_id=1002 287 61 253:3 / /tmp/test rw,relatime shared:236 - ext4 /dev/mapper/fedora-test rw,seclabel,data=ordered 217 23 0:42 / /run/user/1000 rw,nosuid,nodev,relatime shared:168 - tmpfs tmpfs rw,seclabel,size=397432k,mode=700,uid=1000,gid=1000 225 217 0:43 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:175 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000 COREDUMP_ROOT=/ PRIORITY=2 CODE_FILE=src/coredump/coredump.c SYSLOG_IDENTIFIER=lt-systemd-coredump _COMM=lt-systemd-core _SYSTEMD_CGROUP=/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service _SYSTEMD_USER_UNIT=gnome-terminal-server.service MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95 CODE_FUNC=process_traceback COREDUMP_COMM=python3 COREDUMP_EXE=/usr/bin/python3.5 COREDUMP_CMDLINE=python3 systemd_coredump_exception_handler.py COREDUMP_CWD=/home/zbyszek/src/systemd-coredump-python COREDUMP_RLIMIT=-1 COREDUMP_OPEN_FDS=0:/dev/pts/1 pos: 0 flags: 0102002 mnt_id: 22 1:/dev/pts/1 pos: 0 flags: 0102002 mnt_id: 22 2:/dev/pts/1 pos: 0 flags: 0102002 mnt_id: 22 CODE_LINE=1284 COREDUMP_SIGNAL=ZeroDivisionError: division by zero COREDUMP_ENVIRON=LANG=en_US.utf8 DISPLAY=:0 ... MANWIDTH=90 LC_MESSAGES=en_US.utf8 PYTHONPATH=. _=/usr/bin/python3 COREDUMP_PID=14498 COREDUMP_PROC_STATUS=Name: python3 Umask: 0002 State: S (sleeping) Tgid: 14498 Ngid: 0 Pid: 14498 PPid: 16245 TracerPid: 0 Uid: 1002 1002 1002 1002 Gid: 1002 1002 1002 1002 FDSize: 64 Groups: NStgid: 14498 NSpid: 14498 NSpgid: 14498 NSsid: 16245 VmPeak: 34840 kB VmSize: 34792 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 9332 kB VmRSS: 9332 kB RssAnon: 4872 kB RssFile: 4460 kB RssShmem: 0 kB VmData: 5012 kB VmStk: 136 kB VmExe: 4 kB VmLib: 5452 kB VmPTE: 84 kB VmPMD: 12 kB VmSwap: 0 kB HugetlbPages: 0 kB Threads: 1 SigQ: 0/15413 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: 0000000001001000 SigCgt: 0000000180000002 CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: 0000003fffffffff CapAmb: 0000000000000000 Seccomp: 0 Cpus_allowed: f Cpus_allowed_list: 0-3 Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 Mems_allowed_list: 0 voluntary_ctxt_switches: 2 nonvoluntary_ctxt_switches: 47 COREDUMP_PROC_MAPS=55cb7b7fe000-55cb7b7ff000 r-xp 00000000 00:1a 5289186 /usr/bin/python3.5 55cb7b9ff000-55cb7ba00000 r--p 00001000 00:1a 5289186 /usr/bin/python3.5 55cb7ba00000-55cb7ba01000 rw-p 00002000 00:1a 5289186 /usr/bin/python3.5 55cb7c007000-55cb7c189000 rw-p 00000000 00:00 0 [heap] 7f4da2d51000-7f4da2d54000 r-xp 00000000 00:1a 5279150 /usr/lib64/python3.5/lib-dynload/resource.cpython-35m-x86_64-linux-gnu.so 7f4da2d54000-7f4da2f53000 ---p 00003000 00:1a 5279150 /usr/lib64/python3.5/lib-dynload/resource.cpython-35m-x86_64-linux-gnu.so 7f4da2f53000-7f4da2f54000 r--p 00002000 00:1a 5279150 /usr/lib64/python3.5/lib-dynload/resource.cpython-35m-x86_64-linux-gnu.so 7f4da2f54000-7f4da2f55000 rw-p 00003000 00:1a 5279150 /usr/lib64/python3.5/lib-dynload/resource.cpython-35m-x86_64-linux-gnu.so 7f4da2f55000-7f4da2f5d000 r-xp 00000000 00:1a 5279143 /usr/lib64/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so 7f4da2f5d000-7f4da315c000 ---p 00008000 00:1a 5279143 /usr/lib64/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so 7f4da315c000-7f4da315d000 r--p 00007000 00:1a 5279143 /usr/lib64/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so 7f4da315d000-7f4da315f000 rw-p 00008000 00:1a 5279143 /usr/lib64/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so 7f4da315f000-7f4da319f000 rw-p 00000000 00:00 0 7f4da319f000-7f4da31a4000 r-xp 00000000 00:1a 5279151 /usr/lib64/python3.5/lib-dynload/select.cpython-35m-x86_64-linux-gnu.so 7f4da31a4000-7f4da33a3000 ---p 00005000 00:1a 5279151 /usr/lib64/python3.5/lib-dynload/select.cpython-35m-x86_64-linux-gnu.so 7f4da33a3000-7f4da33a4000 r--p 00004000 00:1a 5279151 /usr/lib64/python3.5/lib-dynload/select.cpython-35m-x86_64-linux-gnu.so 7f4da33a4000-7f4da33a6000 rw-p 00005000 00:1a 5279151 /usr/lib64/python3.5/lib-dynload/select.cpython-35m-x86_64-linux-gnu.so 7f4da33a6000-7f4da33a9000 r-xp 00000000 00:1a 5279130 /usr/lib64/python3.5/lib-dynload/_posixsubprocess.cpython-35m-x86_64-linux-gnu.so 7f4da33a9000-7f4da35a8000 ---p 00003000 00:1a 5279130 /usr/lib64/python3.5/lib-dynload/_posixsubprocess.cpython-35m-x86_64-linux-gnu.so 7f4da35a8000-7f4da35a9000 r--p 00002000 00:1a 5279130 /usr/lib64/python3.5/lib-dynload/_posixsubprocess.cpython-35m-x86_64-linux-gnu.so 7f4da35a9000-7f4da35aa000 rw-p 00003000 00:1a 5279130 /usr/lib64/python3.5/lib-dynload/_posixsubprocess.cpython-35m-x86_64-linux-gnu.so 7f4da35aa000-7f4da362a000 rw-p 00000000 00:00 0 7f4da362a000-7f4da362c000 r-xp 00000000 00:1a 5279122 /usr/lib64/python3.5/lib-dynload/_heapq.cpython-35m-x86_64-linux-gnu.so 7f4da362c000-7f4da382b000 ---p 00002000 00:1a 5279122 /usr/lib64/python3.5/lib-dynload/_heapq.cpython-35m-x86_64-linux-gnu.so 7f4da382b000-7f4da382c000 r--p 00001000 00:1a 5279122 /usr/lib64/python3.5/lib-dynload/_heapq.cpython-35m-x86_64-linux-gnu.so 7f4da382c000-7f4da382e000 rw-p 00002000 00:1a 5279122 /usr/lib64/python3.5/lib-dynload/_heapq.cpython-35m-x86_64-linux-gnu.so 7f4da382e000-7f4da39ee000 rw-p 00000000 00:00 0 7f4da39ee000-7f4da3bab000 r-xp 00000000 00:1a 4844904 /usr/lib64/libc-2.24.so 7f4da3bab000-7f4da3daa000 ---p 001bd000 00:1a 4844904 /usr/lib64/libc-2.24.so 7f4da3daa000-7f4da3dae000 r--p 001bc000 00:1a 4844904 /usr/lib64/libc-2.24.so 7f4da3dae000-7f4da3db0000 rw-p 001c0000 00:1a 4844904 /usr/lib64/libc-2.24.so 7f4da3db0000-7f4da3db4000 rw-p 00000000 00:00 0 7f4da3db4000-7f4da3ebc000 r-xp 00000000 00:1a 4844910 /usr/lib64/libm-2.24.so 7f4da3ebc000-7f4da40bb000 ---p 00108000 00:1a 4844910 /usr/lib64/libm-2.24.so 7f4da40bb000-7f4da40bc000 r--p 00107000 00:1a 4844910 /usr/lib64/libm-2.24.so 7f4da40bc000-7f4da40bd000 rw-p 00108000 00:1a 4844910 /usr/lib64/libm-2.24.so 7f4da40bd000-7f4da40bf000 r-xp 00000000 00:1a 4844928 /usr/lib64/libutil-2.24.so 7f4da40bf000-7f4da42be000 ---p 00002000 00:1a 4844928 /usr/lib64/libutil-2.24.so 7f4da42be000-7f4da42bf000 r--p 00001000 00:1a 4844928 /usr/lib64/libutil-2.24.so 7f4da42bf000-7f4da42c0000 rw-p 00002000 00:1a 4844928 /usr/lib64/libutil-2.24.so 7f4da42c0000-7f4da42c3000 r-xp 00000000 00:1a 4844908 /usr/lib64/libdl-2.24.so 7f4da42c3000-7f4da44c2000 ---p 00003000 00:1a 4844908 /usr/lib64/libdl-2.24.so 7f4da44c2000-7f4da44c3000 r--p 00002000 00:1a 4844908 /usr/lib64/libdl-2.24.so 7f4da44c3000-7f4da44c4000 rw-p 00003000 00:1a 4844908 /usr/lib64/libdl-2.24.so 7f4da44c4000-7f4da44dc000 r-xp 00000000 00:1a 4844920 /usr/lib64/libpthread-2.24.so 7f4da44dc000-7f4da46dc000 ---p 00018000 00:1a 4844920 /usr/lib64/libpthread-2.24.so 7f4da46dc000-7f4da46dd000 r--p 00018000 00:1a 4844920 /usr/lib64/libpthread-2.24.so 7f4da46dd000-7f4da46de000 rw-p 00019000 00:1a 4844920 /usr/lib64/libpthread-2.24.so 7f4da46de000-7f4da46e2000 rw-p 00000000 00:00 0 7f4da46e2000-7f4da4917000 r-xp 00000000 00:1a 5277535 /usr/lib64/libpython3.5m.so.1.0 7f4da4917000-7f4da4b17000 ---p 00235000 00:1a 5277535 /usr/lib64/libpython3.5m.so.1.0 7f4da4b17000-7f4da4b1c000 r--p 00235000 00:1a 5277535 /usr/lib64/libpython3.5m.so.1.0 7f4da4b1c000-7f4da4b7f000 rw-p 0023a000 00:1a 5277535 /usr/lib64/libpython3.5m.so.1.0 7f4da4b7f000-7f4da4baf000 rw-p 00000000 00:00 0 7f4da4baf000-7f4da4bd4000 r-xp 00000000 00:1a 4844897 /usr/lib64/ld-2.24.so 7f4da4bdf000-7f4da4c10000 rw-p 00000000 00:00 0 7f4da4c10000-7f4da4c61000 r--p 00000000 00:1a 5225117 /usr/lib/locale/pl_PL.utf8/LC_CTYPE 7f4da4c61000-7f4da4d91000 r--p 00000000 00:1a 4844827 /usr/lib/locale/en_US.utf8/LC_COLLATE 7f4da4d91000-7f4da4d95000 rw-p 00000000 00:00 0 7f4da4dc1000-7f4da4dc2000 r--p 00000000 00:1a 4844832 /usr/lib/locale/en_US.utf8/LC_NUMERIC 7f4da4dc2000-7f4da4dc3000 r--p 00000000 00:1a 4844795 /usr/lib/locale/en_US.utf8/LC_TIME 7f4da4dc3000-7f4da4dc4000 r--p 00000000 00:1a 4844793 /usr/lib/locale/en_US.utf8/LC_MONETARY 7f4da4dc4000-7f4da4dc5000 r--p 00000000 00:1a 4844830 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES 7f4da4dc5000-7f4da4dc6000 r--p 00000000 00:1a 4844847 /usr/lib/locale/en_US.utf8/LC_PAPER 7f4da4dc6000-7f4da4dc7000 r--p 00000000 00:1a 4844831 /usr/lib/locale/en_US.utf8/LC_NAME 7f4da4dc7000-7f4da4dc8000 r--p 00000000 00:1a 4844790 /usr/lib/locale/en_US.utf8/LC_ADDRESS 7f4da4dc8000-7f4da4dc9000 r--p 00000000 00:1a 4844794 /usr/lib/locale/en_US.utf8/LC_TELEPHONE 7f4da4dc9000-7f4da4dca000 r--p 00000000 00:1a 4844792 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT 7f4da4dca000-7f4da4dd1000 r--s 00000000 00:1a 4845203 /usr/lib64/gconv/gconv-modules.cache 7f4da4dd1000-7f4da4dd2000 r--p 00000000 00:1a 4844791 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION 7f4da4dd2000-7f4da4dd4000 rw-p 00000000 00:00 0 7f4da4dd4000-7f4da4dd5000 r--p 00025000 00:1a 4844897 /usr/lib64/ld-2.24.so 7f4da4dd5000-7f4da4dd6000 rw-p 00026000 00:1a 4844897 /usr/lib64/ld-2.24.so 7f4da4dd6000-7f4da4dd7000 rw-p 00000000 00:00 0 7ffd24da1000-7ffd24dc2000 rw-p 00000000 00:00 0 [stack] 7ffd24de8000-7ffd24dea000 r--p 00000000 00:00 0 [vvar] 7ffd24dea000-7ffd24dec000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] COREDUMP_TIMESTAMP=1477877460000000 MESSAGE=Process 14498 (python3) of user 1002 failed with ZeroDivisionError: division by zero: Traceback (most recent call last): File "systemd_coredump_exception_handler.py", line 89, in g() File "systemd_coredump_exception_handler.py", line 88, in g f() File "systemd_coredump_exception_handler.py", line 86, in f div0 = 1 / 0 # pylint: disable=W0612 ZeroDivisionError: division by zero Local variables in innermost frame: h= a=3 _PID=14499 _SOURCE_REALTIME_TIMESTAMP=1477877460025975 --- man/coredump.conf.xml | 2 +- src/coredump/coredump.c | 97 +++++++++++++++++++++++++++++++++++++++++++---- src/systemd/sd-messages.h | 1 + 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/man/coredump.conf.xml b/man/coredump.conf.xml index 77b4dac51c..5f61e05f40 100644 --- a/man/coredump.conf.xml +++ b/man/coredump.conf.xml @@ -85,7 +85,7 @@ Controls where to store cores. One of none, external, and journal. When - none, the core dumps will be logged (included the traceback if + none, the core dumps will be logged (including the backtrace if possible), but not stored permanently. When external (the default), cores will be stored in /var/lib/systemd/coredump/. When journal, cores will be stored in the journal and rotated diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index d5b638d7ec..4d66b59fd6 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -830,6 +830,8 @@ static int process_socket(int fd) { log_parse_environment(); log_open(); + log_debug("Processing coredump received on stdin..."); + for (;;) { union { struct cmsghdr cmsghdr; @@ -1045,6 +1047,7 @@ static char* set_iovec_field_free(struct iovec iovec[27], size_t *n_iovec, const static int gather_pid_metadata( const char *context[_CONTEXT_MAX], char **comm_fallback, + char **comm_ret, struct iovec iovec[27], size_t *n_iovec) { _cleanup_free_ char *exe = NULL, *comm = NULL; @@ -1056,7 +1059,7 @@ static int gather_pid_metadata( r = parse_pid(context[CONTEXT_PID], &pid); if (r < 0) - return log_error_errno(r, "Failed to parse PID."); + return log_error_errno(r, "Failed to parse PID \"%s\": %m", context[CONTEXT_PID]); r = get_process_comm(pid, &comm); if (r < 0) { @@ -1182,6 +1185,11 @@ static int gather_pid_metadata( if (t) IOVEC_SET_STRING(iovec[(*n_iovec)++], t); + if (comm_ret) { + *comm_ret = comm; + comm = NULL; + } + return 0; } @@ -1189,11 +1197,13 @@ static int process_kernel(int argc, char* argv[]) { const char *context[_CONTEXT_MAX]; struct iovec iovec[27]; - size_t n_iovec = 0, i, n_to_free; + size_t i, n_iovec, n_to_free = 0; int r; + log_debug("Processing coredump received from the kernel..."); + if (argc < CONTEXT_COMM + 1) { - log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); + log_error("Not enough arguments passed by the kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); return -EINVAL; } @@ -1204,10 +1214,10 @@ static int process_kernel(int argc, char* argv[]) { context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1]; context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1]; - r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, iovec, &n_iovec); + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, NULL, iovec, &n_to_free); if (r < 0) goto finish; - n_to_free = n_iovec; + n_iovec = n_to_free; IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); @@ -1225,6 +1235,74 @@ static int process_kernel(int argc, char* argv[]) { return r; } +static int process_backtrace(int argc, char *argv[]) { + const char *context[_CONTEXT_MAX]; + char *t; + _cleanup_free_ char *comm = NULL; + struct iovec iovec[27]; + size_t n_iovec = 0, i, n_to_free; + uint8_t buf[4096]; + ssize_t buf_bytes; + int r; + + log_debug("Processing backtrace on stdin..."); + + if (argc < CONTEXT_COMM + 1) { + log_error("Not enough arguments passed (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); + return -EINVAL; + } + + context[CONTEXT_PID] = argv[CONTEXT_PID + 2]; + context[CONTEXT_UID] = argv[CONTEXT_UID + 2]; + context[CONTEXT_GID] = argv[CONTEXT_GID + 2]; + context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 2]; + context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 2]; + context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 2]; + + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_iovec); + if (r < 0) + goto finish; + + if (isempty(context[CONTEXT_SIGNAL])) + context[CONTEXT_SIGNAL] = "an exception"; + + buf_bytes = loop_read(STDIN_FILENO, buf, sizeof(buf) - 1, false); + if (buf_bytes < 0) { + log_error_errno(buf_bytes, "Failed to read backtrace from stdin: %m"); + goto finish; + } + buf[buf_bytes] = '\0'; + + t = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", comm, ")" + " of user ", context[CONTEXT_UID], + " failed with ", context[CONTEXT_SIGNAL], + ":\n\n", buf, NULL); + if (!t) { + log_oom(); + goto finish; + } + IOVEC_SET_STRING(iovec[n_iovec++], t); + + n_to_free = n_iovec; + + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95"); + + assert_cc(2 == LOG_CRIT); + IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); + + assert(n_iovec <= ELEMENTSOF(iovec)); + + r = sd_journal_sendv(iovec, n_iovec); + if (r < 0) + log_error_errno(r, "Failed to log backtrace: %m"); + + finish: + for (i = 0; i < n_to_free; i++) + free(iovec[i].iov_base); + + return r; +} + int main(int argc, char *argv[]) { int r; @@ -1251,9 +1329,12 @@ int main(int argc, char *argv[]) { /* If we got an fd passed, we are running in coredumpd mode. Otherwise we * are invoked from the kernel as coredump handler. */ - if (r == 0) - r = process_kernel(argc, argv); - else if (r == 1) + if (r == 0) { + if (streq_ptr(argv[1], "--backtrace")) + r = process_backtrace(argc, argv); + else + r = process_kernel(argc, argv); + } else if (r == 1) r = process_socket(SD_LISTEN_FDS_START); else { log_error("Received unexpected number of file descriptors."); diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index db1a21be05..542e900744 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -41,6 +41,7 @@ _SD_BEGIN_DECLARATIONS; #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) #define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_BACKTRACE SD_ID128_MAKE(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) #define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) #define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) -- cgit v1.2.3-54-g00ecf From b18453eda671277e44d4097e6f33b609d14a2d73 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 5 Nov 2016 22:40:54 -0400 Subject: Move export format parsing from src/journal-remote/ to src/basic/ No functional change. --- Makefile.am | 4 +- src/basic/journal-importer.c | 481 ++++++++++++++++++++++++++++++ src/basic/journal-importer.h | 70 +++++ src/coredump/coredump.c | 2 +- src/journal-remote/journal-remote-parse.c | 431 +------------------------- src/journal-remote/journal-remote-parse.h | 35 +-- src/journal-remote/journal-remote-write.c | 33 -- src/journal-remote/journal-remote-write.h | 12 +- src/journal-remote/journal-remote.c | 21 +- src/journal/journald-native.c | 1 + src/journal/journald-native.h | 5 - 11 files changed, 582 insertions(+), 513 deletions(-) create mode 100644 src/basic/journal-importer.c create mode 100644 src/basic/journal-importer.h diff --git a/Makefile.am b/Makefile.am index c45755f36e..64343b6b26 100644 --- a/Makefile.am +++ b/Makefile.am @@ -960,7 +960,9 @@ libbasic_la_SOURCES = \ src/basic/format-util.h \ src/basic/nss-util.h \ src/basic/khash.h \ - src/basic/khash.c + src/basic/khash.c \ + src/basic/journal-importer.h \ + src/basic/journal-importer.c nodist_libbasic_la_SOURCES = \ src/basic/errno-from-name.h \ diff --git a/src/basic/journal-importer.c b/src/basic/journal-importer.c new file mode 100644 index 0000000000..4c13e46a49 --- /dev/null +++ b/src/basic/journal-importer.c @@ -0,0 +1,481 @@ +/*** + This file is part of systemd. + + Copyright 2014 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "alloc-util.h" +#include "journal-importer.h" +#include "fd-util.h" +#include "parse-util.h" +#include "string-util.h" + +enum { + IMPORTER_STATE_LINE = 0, /* waiting to read, or reading line */ + IMPORTER_STATE_DATA_START, /* reading binary data header */ + IMPORTER_STATE_DATA, /* reading binary data */ + IMPORTER_STATE_DATA_FINISH, /* expecting newline */ + IMPORTER_STATE_EOF, /* done */ +}; + +static int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) { + if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1)) + return log_oom(); + + iovw->iovec[iovw->count++] = (struct iovec) {data, len}; + return 0; +} + +static void iovw_free_contents(struct iovec_wrapper *iovw) { + iovw->iovec = mfree(iovw->iovec); + iovw->size_bytes = iovw->count = 0; +} + +static void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) { + size_t i; + + for (i = 0; i < iovw->count; i++) + iovw->iovec[i].iov_base = (char*) iovw->iovec[i].iov_base - old + new; +} + +size_t iovw_size(struct iovec_wrapper *iovw) { + size_t n = 0, i; + + for (i = 0; i < iovw->count; i++) + n += iovw->iovec[i].iov_len; + + return n; +} + +void journal_importer_cleanup(JournalImporter *imp) { + if (imp->fd >= 0 && !imp->passive_fd) { + log_debug("Closing %s (fd=%d)", imp->name ?: "importer", imp->fd); + safe_close(imp->fd); + } + + free(imp->buf); + iovw_free_contents(&imp->iovw); +} + +static char* realloc_buffer(JournalImporter *imp, size_t size) { + char *b, *old = imp->buf; + + b = GREEDY_REALLOC(imp->buf, imp->size, size); + if (!b) + return NULL; + + iovw_rebase(&imp->iovw, old, imp->buf); + + return b; +} + +static int get_line(JournalImporter *imp, char **line, size_t *size) { + ssize_t n; + char *c = NULL; + + assert(imp); + assert(imp->state == IMPORTER_STATE_LINE); + assert(imp->offset <= imp->filled); + assert(imp->filled <= imp->size); + assert(imp->buf == NULL || imp->size > 0); + assert(imp->fd >= 0); + + for (;;) { + if (imp->buf) { + size_t start = MAX(imp->scanned, imp->offset); + + c = memchr(imp->buf + start, '\n', + imp->filled - start); + if (c != NULL) + break; + } + + imp->scanned = imp->filled; + if (imp->scanned >= DATA_SIZE_MAX) { + log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX); + return -E2BIG; + } + + if (imp->passive_fd) + /* we have to wait for some data to come to us */ + return -EAGAIN; + + /* We know that imp->filled is at most DATA_SIZE_MAX, so if + we reallocate it, we'll increase the size at least a bit. */ + assert_cc(DATA_SIZE_MAX < ENTRY_SIZE_MAX); + if (imp->size - imp->filled < LINE_CHUNK && + !realloc_buffer(imp, MIN(imp->filled + LINE_CHUNK, ENTRY_SIZE_MAX))) + return log_oom(); + + assert(imp->buf); + assert(imp->size - imp->filled >= LINE_CHUNK || + imp->size == ENTRY_SIZE_MAX); + + n = read(imp->fd, + imp->buf + imp->filled, + imp->size - imp->filled); + if (n < 0) { + if (errno != EAGAIN) + log_error_errno(errno, "read(%d, ..., %zu): %m", + imp->fd, + imp->size - imp->filled); + return -errno; + } else if (n == 0) + return 0; + + imp->filled += n; + } + + *line = imp->buf + imp->offset; + *size = c + 1 - imp->buf - imp->offset; + imp->offset += *size; + + return 1; +} + +static int fill_fixed_size(JournalImporter *imp, void **data, size_t size) { + + assert(imp); + assert(imp->state == IMPORTER_STATE_DATA_START || + imp->state == IMPORTER_STATE_DATA || + imp->state == IMPORTER_STATE_DATA_FINISH); + assert(size <= DATA_SIZE_MAX); + assert(imp->offset <= imp->filled); + assert(imp->filled <= imp->size); + assert(imp->buf != NULL || imp->size == 0); + assert(imp->buf == NULL || imp->size > 0); + assert(imp->fd >= 0); + assert(data); + + while (imp->filled - imp->offset < size) { + int n; + + if (imp->passive_fd) + /* we have to wait for some data to come to us */ + return -EAGAIN; + + if (!realloc_buffer(imp, imp->offset + size)) + return log_oom(); + + n = read(imp->fd, imp->buf + imp->filled, + imp->size - imp->filled); + if (n < 0) { + if (errno != EAGAIN) + log_error_errno(errno, "read(%d, ..., %zu): %m", imp->fd, + imp->size - imp->filled); + return -errno; + } else if (n == 0) + return 0; + + imp->filled += n; + } + + *data = imp->buf + imp->offset; + imp->offset += size; + + return 1; +} + +static int get_data_size(JournalImporter *imp) { + int r; + void *data; + + assert(imp); + assert(imp->state == IMPORTER_STATE_DATA_START); + assert(imp->data_size == 0); + + r = fill_fixed_size(imp, &data, sizeof(uint64_t)); + if (r <= 0) + return r; + + imp->data_size = le64toh( *(uint64_t *) data ); + if (imp->data_size > DATA_SIZE_MAX) { + log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u", + imp->data_size, DATA_SIZE_MAX); + return -EINVAL; + } + if (imp->data_size == 0) + log_warning("Binary field with zero length"); + + return 1; +} + +static int get_data_data(JournalImporter *imp, void **data) { + int r; + + assert(imp); + assert(data); + assert(imp->state == IMPORTER_STATE_DATA); + + r = fill_fixed_size(imp, data, imp->data_size); + if (r <= 0) + return r; + + return 1; +} + +static int get_data_newline(JournalImporter *imp) { + int r; + char *data; + + assert(imp); + assert(imp->state == IMPORTER_STATE_DATA_FINISH); + + r = fill_fixed_size(imp, (void**) &data, 1); + if (r <= 0) + return r; + + assert(data); + if (*data != '\n') { + log_error("expected newline, got '%c'", *data); + return -EINVAL; + } + + return 1; +} + +static int process_dunder(JournalImporter *imp, char *line, size_t n) { + const char *timestamp; + int r; + + assert(line); + assert(n > 0); + assert(line[n-1] == '\n'); + + /* XXX: is it worth to support timestamps in extended format? + * We don't produce them, but who knows... */ + + timestamp = startswith(line, "__CURSOR="); + if (timestamp) + /* ignore __CURSOR */ + return 1; + + timestamp = startswith(line, "__REALTIME_TIMESTAMP="); + if (timestamp) { + long long unsigned x; + line[n-1] = '\0'; + r = safe_atollu(timestamp, &x); + if (r < 0) + log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp); + else + imp->ts.realtime = x; + return r < 0 ? r : 1; + } + + timestamp = startswith(line, "__MONOTONIC_TIMESTAMP="); + if (timestamp) { + long long unsigned x; + line[n-1] = '\0'; + r = safe_atollu(timestamp, &x); + if (r < 0) + log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp); + else + imp->ts.monotonic = x; + return r < 0 ? r : 1; + } + + timestamp = startswith(line, "__"); + if (timestamp) { + log_notice("Unknown dunder line %s", line); + return 1; + } + + /* no dunder */ + return 0; +} + +int journal_importer_process_data(JournalImporter *imp) { + int r; + + switch(imp->state) { + case IMPORTER_STATE_LINE: { + char *line, *sep; + size_t n = 0; + + assert(imp->data_size == 0); + + r = get_line(imp, &line, &n); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return r; + } + assert(n > 0); + assert(line[n-1] == '\n'); + + if (n == 1) { + log_trace("Received empty line, event is ready"); + return 1; + } + + r = process_dunder(imp, line, n); + if (r != 0) + return r < 0 ? r : 0; + + /* MESSAGE=xxx\n + or + COREDUMP\n + LLLLLLLL0011223344...\n + */ + sep = memchr(line, '=', n); + if (sep) { + /* chomp newline */ + n--; + + r = iovw_put(&imp->iovw, line, n); + if (r < 0) + return r; + } else { + /* replace \n with = */ + line[n-1] = '='; + + imp->field_len = n; + imp->state = IMPORTER_STATE_DATA_START; + + /* we cannot put the field in iovec until we have all data */ + } + + log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary"); + + return 0; /* continue */ + } + + case IMPORTER_STATE_DATA_START: + assert(imp->data_size == 0); + + r = get_data_size(imp); + // log_debug("get_data_size() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + imp->state = imp->data_size > 0 ? + IMPORTER_STATE_DATA : IMPORTER_STATE_DATA_FINISH; + + return 0; /* continue */ + + case IMPORTER_STATE_DATA: { + void *data; + char *field; + + assert(imp->data_size > 0); + + r = get_data_data(imp, &data); + // log_debug("get_data_data() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + assert(data); + + field = (char*) data - sizeof(uint64_t) - imp->field_len; + memmove(field + sizeof(uint64_t), field, imp->field_len); + + r = iovw_put(&imp->iovw, field + sizeof(uint64_t), imp->field_len + imp->data_size); + if (r < 0) + return r; + + imp->state = IMPORTER_STATE_DATA_FINISH; + + return 0; /* continue */ + } + + case IMPORTER_STATE_DATA_FINISH: + r = get_data_newline(imp); + // log_debug("get_data_newline() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + imp->data_size = 0; + imp->state = IMPORTER_STATE_LINE; + + return 0; /* continue */ + default: + assert_not_reached("wtf?"); + } +} + +int journal_importer_push_data(JournalImporter *imp, const char *data, size_t size) { + assert(imp); + assert(imp->state != IMPORTER_STATE_EOF); + + if (!realloc_buffer(imp, imp->filled + size)) { + log_error("Failed to store received data of size %zu " + "(in addition to existing %zu bytes with %zu filled): %s", + size, imp->size, imp->filled, strerror(ENOMEM)); + return -ENOMEM; + } + + memcpy(imp->buf + imp->filled, data, size); + imp->filled += size; + + return 0; +} + +void journal_importer_drop_iovw(JournalImporter *imp) { + size_t remain, target; + + /* This function drops processed data that along with the iovw that points at it */ + + iovw_free_contents(&imp->iovw); + + /* possibly reset buffer position */ + remain = imp->filled - imp->offset; + + if (remain == 0) /* no brainer */ + imp->offset = imp->scanned = imp->filled = 0; + else if (imp->offset > imp->size - imp->filled && + imp->offset > remain) { + memcpy(imp->buf, imp->buf + imp->offset, remain); + imp->offset = imp->scanned = 0; + imp->filled = remain; + } + + target = imp->size; + while (target > 16 * LINE_CHUNK && imp->filled < target / 2) + target /= 2; + if (target < imp->size) { + char *tmp; + + tmp = realloc(imp->buf, target); + if (!tmp) + log_warning("Failed to reallocate buffer to (smaller) size %zu", + target); + else { + log_debug("Reallocated buffer from %zu to %zu bytes", + imp->size, target); + imp->buf = tmp; + imp->size = target; + } + } +} + +bool journal_importer_eof(const JournalImporter *imp) { + return imp->state == IMPORTER_STATE_EOF; +} diff --git a/src/basic/journal-importer.h b/src/basic/journal-importer.h new file mode 100644 index 0000000000..b3e308dd6d --- /dev/null +++ b/src/basic/journal-importer.h @@ -0,0 +1,70 @@ +/*** + This file is part of systemd. + + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#pragma once + +#include +#include +#include + +#include "time-util.h" + +/* Make sure not to make this smaller than the maximum coredump size. + * See COREDUMP_MAX in coredump.c */ +#define ENTRY_SIZE_MAX (1024*1024*770u) +#define DATA_SIZE_MAX (1024*1024*768u) +#define LINE_CHUNK 8*1024u + +struct iovec_wrapper { + struct iovec *iovec; + size_t size_bytes; + size_t count; +}; + +size_t iovw_size(struct iovec_wrapper *iovw); + +typedef struct JournalImporter { + int fd; + bool passive_fd; + char *name; + + char *buf; + size_t size; /* total size of the buffer */ + size_t offset; /* offset to the beginning of live data in the buffer */ + size_t scanned; /* number of bytes since the beginning of data without a newline */ + size_t filled; /* total number of bytes in the buffer */ + + size_t field_len; /* used for binary fields: the field name length */ + size_t data_size; /* and the size of the binary data chunk being processed */ + + struct iovec_wrapper iovw; + + int state; + dual_timestamp ts; +} JournalImporter; + +void journal_importer_cleanup(JournalImporter *); +int journal_importer_process_data(JournalImporter *); +int journal_importer_push_data(JournalImporter *, const char *data, size_t size); +void journal_importer_drop_iovw(JournalImporter *); +bool journal_importer_eof(const JournalImporter *); + +static inline size_t journal_importer_bytes_remaining(const JournalImporter *imp) { + return imp->filled; +} diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 4d66b59fd6..2d9819e5b0 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -47,7 +47,7 @@ #include "fileio.h" #include "fs-util.h" #include "io-util.h" -#include "journald-native.h" +#include "journal-importer.h" #include "log.h" #include "macro.h" #include "missing.h" diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c index 9ba9ee3fc0..79afe6604c 100644 --- a/src/journal-remote/journal-remote-parse.c +++ b/src/journal-remote/journal-remote-parse.c @@ -24,20 +24,11 @@ #include "parse-util.h" #include "string-util.h" -#define LINE_CHUNK 8*1024u - void source_free(RemoteSource *source) { if (!source) return; - if (source->fd >= 0 && !source->passive_fd) { - log_debug("Closing fd:%d (%s)", source->fd, source->name); - safe_close(source->fd); - } - - free(source->name); - free(source->buf); - iovw_free_contents(&source->iovw); + journal_importer_cleanup(&source->importer); log_debug("Writer ref count %i", source->writer->n_ref); writer_unref(source->writer); @@ -65,442 +56,44 @@ RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) { if (!source) return NULL; - source->fd = fd; - source->passive_fd = passive_fd; - source->name = name; + source->importer.fd = fd; + source->importer.passive_fd = passive_fd; + source->importer.name = name; + source->writer = writer; return source; } -static char* realloc_buffer(RemoteSource *source, size_t size) { - char *b, *old = source->buf; - - b = GREEDY_REALLOC(source->buf, source->size, size); - if (!b) - return NULL; - - iovw_rebase(&source->iovw, old, source->buf); - - return b; -} - -static int get_line(RemoteSource *source, char **line, size_t *size) { - ssize_t n; - char *c = NULL; - - assert(source); - assert(source->state == STATE_LINE); - assert(source->offset <= source->filled); - assert(source->filled <= source->size); - assert(source->buf == NULL || source->size > 0); - assert(source->fd >= 0); - - for (;;) { - if (source->buf) { - size_t start = MAX(source->scanned, source->offset); - - c = memchr(source->buf + start, '\n', - source->filled - start); - if (c != NULL) - break; - } - - source->scanned = source->filled; - if (source->scanned >= DATA_SIZE_MAX) { - log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX); - return -E2BIG; - } - - if (source->passive_fd) - /* we have to wait for some data to come to us */ - return -EAGAIN; - - /* We know that source->filled is at most DATA_SIZE_MAX, so if - we reallocate it, we'll increase the size at least a bit. */ - assert_cc(DATA_SIZE_MAX < ENTRY_SIZE_MAX); - if (source->size - source->filled < LINE_CHUNK && - !realloc_buffer(source, MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX))) - return log_oom(); - - assert(source->buf); - assert(source->size - source->filled >= LINE_CHUNK || - source->size == ENTRY_SIZE_MAX); - - n = read(source->fd, - source->buf + source->filled, - source->size - source->filled); - if (n < 0) { - if (errno != EAGAIN) - log_error_errno(errno, "read(%d, ..., %zu): %m", - source->fd, - source->size - source->filled); - return -errno; - } else if (n == 0) - return 0; - - source->filled += n; - } - - *line = source->buf + source->offset; - *size = c + 1 - source->buf - source->offset; - source->offset += *size; - - return 1; -} - -int push_data(RemoteSource *source, const char *data, size_t size) { - assert(source); - assert(source->state != STATE_EOF); - - if (!realloc_buffer(source, source->filled + size)) { - log_error("Failed to store received data of size %zu " - "(in addition to existing %zu bytes with %zu filled): %s", - size, source->size, source->filled, strerror(ENOMEM)); - return -ENOMEM; - } - - memcpy(source->buf + source->filled, data, size); - source->filled += size; - - return 0; -} - -static int fill_fixed_size(RemoteSource *source, void **data, size_t size) { - - assert(source); - assert(source->state == STATE_DATA_START || - source->state == STATE_DATA || - source->state == STATE_DATA_FINISH); - assert(size <= DATA_SIZE_MAX); - assert(source->offset <= source->filled); - assert(source->filled <= source->size); - assert(source->buf != NULL || source->size == 0); - assert(source->buf == NULL || source->size > 0); - assert(source->fd >= 0); - assert(data); - - while (source->filled - source->offset < size) { - int n; - - if (source->passive_fd) - /* we have to wait for some data to come to us */ - return -EAGAIN; - - if (!realloc_buffer(source, source->offset + size)) - return log_oom(); - - n = read(source->fd, source->buf + source->filled, - source->size - source->filled); - if (n < 0) { - if (errno != EAGAIN) - log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd, - source->size - source->filled); - return -errno; - } else if (n == 0) - return 0; - - source->filled += n; - } - - *data = source->buf + source->offset; - source->offset += size; - - return 1; -} - -static int get_data_size(RemoteSource *source) { - int r; - void *data; - - assert(source); - assert(source->state == STATE_DATA_START); - assert(source->data_size == 0); - - r = fill_fixed_size(source, &data, sizeof(uint64_t)); - if (r <= 0) - return r; - - source->data_size = le64toh( *(uint64_t *) data ); - if (source->data_size > DATA_SIZE_MAX) { - log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u", - source->data_size, DATA_SIZE_MAX); - return -EINVAL; - } - if (source->data_size == 0) - log_warning("Binary field with zero length"); - - return 1; -} - -static int get_data_data(RemoteSource *source, void **data) { - int r; - - assert(source); - assert(data); - assert(source->state == STATE_DATA); - - r = fill_fixed_size(source, data, source->data_size); - if (r <= 0) - return r; - - return 1; -} - -static int get_data_newline(RemoteSource *source) { - int r; - char *data; - - assert(source); - assert(source->state == STATE_DATA_FINISH); - - r = fill_fixed_size(source, (void**) &data, 1); - if (r <= 0) - return r; - - assert(data); - if (*data != '\n') { - log_error("expected newline, got '%c'", *data); - return -EINVAL; - } - - return 1; -} - -static int process_dunder(RemoteSource *source, char *line, size_t n) { - const char *timestamp; - int r; - - assert(line); - assert(n > 0); - assert(line[n-1] == '\n'); - - /* XXX: is it worth to support timestamps in extended format? - * We don't produce them, but who knows... */ - - timestamp = startswith(line, "__CURSOR="); - if (timestamp) - /* ignore __CURSOR */ - return 1; - - timestamp = startswith(line, "__REALTIME_TIMESTAMP="); - if (timestamp) { - long long unsigned x; - line[n-1] = '\0'; - r = safe_atollu(timestamp, &x); - if (r < 0) - log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp); - else - source->ts.realtime = x; - return r < 0 ? r : 1; - } - - timestamp = startswith(line, "__MONOTONIC_TIMESTAMP="); - if (timestamp) { - long long unsigned x; - line[n-1] = '\0'; - r = safe_atollu(timestamp, &x); - if (r < 0) - log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp); - else - source->ts.monotonic = x; - return r < 0 ? r : 1; - } - - timestamp = startswith(line, "__"); - if (timestamp) { - log_notice("Unknown dunder line %s", line); - return 1; - } - - /* no dunder */ - return 0; -} - -static int process_data(RemoteSource *source) { - int r; - - switch(source->state) { - case STATE_LINE: { - char *line, *sep; - size_t n = 0; - - assert(source->data_size == 0); - - r = get_line(source, &line, &n); - if (r < 0) - return r; - if (r == 0) { - source->state = STATE_EOF; - return r; - } - assert(n > 0); - assert(line[n-1] == '\n'); - - if (n == 1) { - log_trace("Received empty line, event is ready"); - return 1; - } - - r = process_dunder(source, line, n); - if (r != 0) - return r < 0 ? r : 0; - - /* MESSAGE=xxx\n - or - COREDUMP\n - LLLLLLLL0011223344...\n - */ - sep = memchr(line, '=', n); - if (sep) { - /* chomp newline */ - n--; - - r = iovw_put(&source->iovw, line, n); - if (r < 0) - return r; - } else { - /* replace \n with = */ - line[n-1] = '='; - - source->field_len = n; - source->state = STATE_DATA_START; - - /* we cannot put the field in iovec until we have all data */ - } - - log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary"); - - return 0; /* continue */ - } - - case STATE_DATA_START: - assert(source->data_size == 0); - - r = get_data_size(source); - // log_debug("get_data_size() -> %d", r); - if (r < 0) - return r; - if (r == 0) { - source->state = STATE_EOF; - return 0; - } - - source->state = source->data_size > 0 ? - STATE_DATA : STATE_DATA_FINISH; - - return 0; /* continue */ - - case STATE_DATA: { - void *data; - char *field; - - assert(source->data_size > 0); - - r = get_data_data(source, &data); - // log_debug("get_data_data() -> %d", r); - if (r < 0) - return r; - if (r == 0) { - source->state = STATE_EOF; - return 0; - } - - assert(data); - - field = (char*) data - sizeof(uint64_t) - source->field_len; - memmove(field + sizeof(uint64_t), field, source->field_len); - - r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size); - if (r < 0) - return r; - - source->state = STATE_DATA_FINISH; - - return 0; /* continue */ - } - - case STATE_DATA_FINISH: - r = get_data_newline(source); - // log_debug("get_data_newline() -> %d", r); - if (r < 0) - return r; - if (r == 0) { - source->state = STATE_EOF; - return 0; - } - - source->data_size = 0; - source->state = STATE_LINE; - - return 0; /* continue */ - default: - assert_not_reached("wtf?"); - } -} - int process_source(RemoteSource *source, bool compress, bool seal) { - size_t remain, target; int r; assert(source); assert(source->writer); - r = process_data(source); + r = journal_importer_process_data(&source->importer); if (r <= 0) return r; /* We have a full event */ log_trace("Received full event from source@%p fd:%d (%s)", - source, source->fd, source->name); + source, source->importer.fd, source->importer.name); - if (!source->iovw.count) { + if (source->importer.iovw.count == 0) { log_warning("Entry with no payload, skipping"); goto freeing; } - assert(source->iovw.iovec); - assert(source->iovw.count); + assert(source->importer.iovw.iovec); - r = writer_write(source->writer, &source->iovw, &source->ts, compress, seal); + r = writer_write(source->writer, &source->importer.iovw, &source->importer.ts, compress, seal); if (r < 0) log_error_errno(r, "Failed to write entry of %zu bytes: %m", - iovw_size(&source->iovw)); + iovw_size(&source->importer.iovw)); else r = 1; freeing: - iovw_free_contents(&source->iovw); - - /* possibly reset buffer position */ - remain = source->filled - source->offset; - - if (remain == 0) /* no brainer */ - source->offset = source->scanned = source->filled = 0; - else if (source->offset > source->size - source->filled && - source->offset > remain) { - memcpy(source->buf, source->buf + source->offset, remain); - source->offset = source->scanned = 0; - source->filled = remain; - } - - target = source->size; - while (target > 16 * LINE_CHUNK && source->filled < target / 2) - target /= 2; - if (target < source->size) { - char *tmp; - - tmp = realloc(source->buf, target); - if (!tmp) - log_warning("Failed to reallocate buffer to (smaller) size %zu", - target); - else { - log_debug("Reallocated buffer from %zu to %zu bytes", - source->size, target); - source->buf = tmp; - source->size = target; - } - } - + journal_importer_drop_iovw(&source->importer); return r; } diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h index 1740a21f92..e3632528cf 100644 --- a/src/journal-remote/journal-remote-parse.h +++ b/src/journal-remote/journal-remote-parse.h @@ -21,34 +21,11 @@ #include "sd-event.h" +#include "journal-importer.h" #include "journal-remote-write.h" -typedef enum { - STATE_LINE = 0, /* waiting to read, or reading line */ - STATE_DATA_START, /* reading binary data header */ - STATE_DATA, /* reading binary data */ - STATE_DATA_FINISH, /* expecting newline */ - STATE_EOF, /* done */ -} source_state; - typedef struct RemoteSource { - char *name; - int fd; - bool passive_fd; - - char *buf; - size_t size; /* total size of the buffer */ - size_t offset; /* offset to the beginning of live data in the buffer */ - size_t scanned; /* number of bytes since the beginning of data without a newline */ - size_t filled; /* total number of bytes in the buffer */ - - size_t field_len; /* used for binary fields: the field name length */ - size_t data_size; /* and the size of the binary data chunk being processed */ - - struct iovec_wrapper iovw; - - source_state state; - dual_timestamp ts; + JournalImporter importer; Writer *writer; @@ -57,13 +34,5 @@ typedef struct RemoteSource { } RemoteSource; RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer); - -static inline size_t source_non_empty(RemoteSource *source) { - assert(source); - - return source->filled; -} - void source_free(RemoteSource *source); -int push_data(RemoteSource *source, const char *data, size_t size); int process_source(RemoteSource *source, bool compress, bool seal); diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 8729372aa3..734cad333f 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -20,39 +20,6 @@ #include "alloc-util.h" #include "journal-remote.h" -int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) { - if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1)) - return log_oom(); - - iovw->iovec[iovw->count++] = (struct iovec) {data, len}; - return 0; -} - -void iovw_free_contents(struct iovec_wrapper *iovw) { - iovw->iovec = mfree(iovw->iovec); - iovw->size_bytes = iovw->count = 0; -} - -size_t iovw_size(struct iovec_wrapper *iovw) { - size_t n = 0, i; - - for (i = 0; i < iovw->count; i++) - n += iovw->iovec[i].iov_len; - - return n; -} - -void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) { - size_t i; - - for (i = 0; i < iovw->count; i++) - iovw->iovec[i].iov_base = (char*) iovw->iovec[i].iov_base - old + new; -} - -/********************************************************************** - ********************************************************************** - **********************************************************************/ - static int do_rotate(JournalFile **f, bool compress, bool seal) { int r = journal_file_rotate(f, compress, seal, NULL); if (r < 0) { diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h index 53ba45fc04..e04af54e55 100644 --- a/src/journal-remote/journal-remote-write.h +++ b/src/journal-remote/journal-remote-write.h @@ -20,20 +20,10 @@ ***/ #include "journal-file.h" +#include "journal-importer.h" typedef struct RemoteServer RemoteServer; -struct iovec_wrapper { - struct iovec *iovec; - size_t size_bytes; - size_t count; -}; - -int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len); -void iovw_free_contents(struct iovec_wrapper *iovw); -size_t iovw_size(struct iovec_wrapper *iovw); -void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); - typedef struct Writer { JournalFile *journal; JournalMetrics metrics; diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index d0d8d936e3..202a5a3f97 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -512,7 +512,8 @@ static int process_http_upload( if (*upload_data_size) { log_trace("Received %zu bytes", *upload_data_size); - r = push_data(source, upload_data, *upload_data_size); + r = journal_importer_push_data(&source->importer, + upload_data, *upload_data_size); if (r < 0) return mhd_respond_oom(connection); @@ -542,7 +543,7 @@ static int process_http_upload( /* The upload is finished */ - remaining = source_non_empty(source); + remaining = journal_importer_bytes_remaining(&source->importer); if (remaining > 0) { log_warning("Premature EOF byte. %zu bytes lost.", remaining); return mhd_respondf(connection, @@ -1036,19 +1037,19 @@ static int handle_raw_source(sd_event_source *event, assert(fd >= 0 && fd < (ssize_t) s->sources_size); source = s->sources[fd]; - assert(source->fd == fd); + assert(source->importer.fd == fd); r = process_source(source, arg_compress, arg_seal); - if (source->state == STATE_EOF) { + if (journal_importer_eof(&source->importer)) { size_t remaining; - log_debug("EOF reached with source fd:%d (%s)", - source->fd, source->name); + log_debug("EOF reached with source %s (fd=%d)", + source->importer.name, source->importer.fd); - remaining = source_non_empty(source); + remaining = journal_importer_bytes_remaining(&source->importer); if (remaining > 0) log_notice("Premature EOF. %zu bytes lost.", remaining); - remove_source(s, source->fd); + remove_source(s, source->importer.fd); log_debug("%zu active sources remaining", s->active); return 0; } else if (r == -E2BIG) { @@ -1072,7 +1073,7 @@ static int dispatch_raw_source_until_block(sd_event_source *event, /* Make sure event stays around even if source is destroyed */ sd_event_source_ref(event); - r = handle_raw_source(event, source->fd, EPOLLIN, server); + r = handle_raw_source(event, source->importer.fd, EPOLLIN, server); if (r != 1) /* No more data for now */ sd_event_source_set_enabled(event, SD_EVENT_OFF); @@ -1105,7 +1106,7 @@ static int dispatch_blocking_source_event(sd_event_source *event, void *userdata) { RemoteSource *source = userdata; - return handle_raw_source(event, source->fd, EPOLLIN, server); + return handle_raw_source(event, source->importer.fd, EPOLLIN, server); } static int accept_connection(const char* type, int fd, diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 0a1ce205c2..3c03b83754 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -27,6 +27,7 @@ #include "fd-util.h" #include "fs-util.h" #include "io-util.h" +#include "journal-importer.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-native.h" diff --git a/src/journal/journald-native.h b/src/journal/journald-native.h index c13b80aa4f..1ab415ac85 100644 --- a/src/journal/journald-native.h +++ b/src/journal/journald-native.h @@ -21,11 +21,6 @@ #include "journald-server.h" -/* Make sure not to make this smaller than the maximum coredump - * size. See COREDUMP_MAX in coredump.c */ -#define ENTRY_SIZE_MAX (1024*1024*770u) -#define DATA_SIZE_MAX (1024*1024*768u) - bool valid_user_field(const char *p, size_t l, bool allow_protected); void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); -- cgit v1.2.3-54-g00ecf From 48ccb60d453b06584e58f6ffca47b2204f9c65db Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 5 Nov 2016 23:27:00 -0400 Subject: test-journal-importer: new test file to check the newly exported importer code Only one test case is added, but it is enough to check basic sanity of the code (single-line and binary fields and trusted fields, allocation and freeing). --- .gitignore | 1 + Makefile.am | 12 ++++++- src/test/test-journal-importer.c | 74 +++++++++++++++++++++++++++++++++++++++ test/journal-data/journal-1.txt | Bin 0 -> 586 bytes 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/test/test-journal-importer.c create mode 100644 test/journal-data/journal-1.txt diff --git a/.gitignore b/.gitignore index fe7859c265..924b995bb3 100644 --- a/.gitignore +++ b/.gitignore @@ -220,6 +220,7 @@ /test-journal /test-journal-enum /test-journal-flush +/test-journal-importer /test-journal-init /test-journal-interleaving /test-journal-match diff --git a/Makefile.am b/Makefile.am index 64343b6b26..fef13fabcd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1598,7 +1598,8 @@ tests += \ test-rlimit-util \ test-signal-util \ test-selinux \ - test-sizeof + test-sizeof \ + test-journal-importer if HAVE_ACL tests += \ @@ -2462,6 +2463,15 @@ test_arphrd_list_SOURCES = \ test_arphrd_list_LDADD = \ libsystemd-shared.la +test_journal_importer_SOURCES = \ + src/test/test-journal-importer.c + +test_journal_importer_LDADD = \ + libsystemd-shared.la + +EXTRA_DIST += \ + test/journal-data/journal-1.txt + # ------------------------------------------------------------------------------ ## .PHONY so it always rebuilds it .PHONY: coverage lcov-run lcov-report coverage-sync diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c new file mode 100644 index 0000000000..fea5c1d51c --- /dev/null +++ b/src/test/test-journal-importer.c @@ -0,0 +1,74 @@ +/*** + This file is part of systemd. + + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "log.h" +#include "journal-importer.h" +#include "string-util.h" +#include "test-helper.h" + +static void assert_iovec_entry(const struct iovec *iovec, const char* content) { + assert_se(strlen(content) == iovec->iov_len); + assert_se(memcmp(content, iovec->iov_base, iovec->iov_len) == 0); +} + +#define COREDUMP_PROC_GROUP \ + "COREDUMP_PROC_CGROUP=1:name=systemd:/\n" \ + "0::/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service\n" + +static void test_basic_parsing(void) { + _cleanup_(journal_importer_cleanup) JournalImporter imp = {}; + int r; + + imp.fd = open(TEST_DATA_DIR("/journal-data/journal-1.txt"), O_RDONLY|O_CLOEXEC); + assert_se(imp.fd >= 0); + + do + r = journal_importer_process_data(&imp); + while (r == 0); + assert_se(r == 1); + + /* We read one entry, so we should get EOF on next read, but not yet */ + assert_se(!journal_importer_eof(&imp)); + + assert_se(imp.iovw.count == 6); + assert_iovec_entry(&imp.iovw.iovec[0], "_BOOT_ID=1531fd22ec84429e85ae888b12fadb91"); + assert_iovec_entry(&imp.iovw.iovec[1], "_TRANSPORT=journal"); + assert_iovec_entry(&imp.iovw.iovec[2], COREDUMP_PROC_GROUP); + assert_iovec_entry(&imp.iovw.iovec[3], "COREDUMP_RLIMIT=-1"); + assert_iovec_entry(&imp.iovw.iovec[4], COREDUMP_PROC_GROUP); + assert_iovec_entry(&imp.iovw.iovec[5], "_SOURCE_REALTIME_TIMESTAMP=1478389147837945"); + + /* Let's check if we get EOF now */ + r = journal_importer_process_data(&imp); + assert_se(r == 0); + assert_se(journal_importer_eof(&imp)); +} + +int main(int argc, char **argv) { + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + + test_basic_parsing(); + + return 0; +} diff --git a/test/journal-data/journal-1.txt b/test/journal-data/journal-1.txt new file mode 100644 index 0000000000..92a9199a93 Binary files /dev/null and b/test/journal-data/journal-1.txt differ -- cgit v1.2.3-54-g00ecf From f06a6bcd761f2a643377b17c16776512404ac3b0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 01:01:17 -0400 Subject: test-journal-importer: add a test case with broken input --- Makefile.am | 3 ++- src/test/test-journal-importer.c | 18 +++++++++++++++++- test/journal-data/journal-2.txt | Bin 0 -> 513 bytes 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 test/journal-data/journal-2.txt diff --git a/Makefile.am b/Makefile.am index fef13fabcd..10839e922a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2470,7 +2470,8 @@ test_journal_importer_LDADD = \ libsystemd-shared.la EXTRA_DIST += \ - test/journal-data/journal-1.txt + test/journal-data/journal-1.txt \ + test/journal-data/journal-2.txt # ------------------------------------------------------------------------------ ## .PHONY so it always rebuilds it diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c index fea5c1d51c..1f0684863e 100644 --- a/src/test/test-journal-importer.c +++ b/src/test/test-journal-importer.c @@ -44,7 +44,7 @@ static void test_basic_parsing(void) { do r = journal_importer_process_data(&imp); - while (r == 0); + while (r == 0 && !journal_importer_eof(&imp)); assert_se(r == 1); /* We read one entry, so we should get EOF on next read, but not yet */ @@ -64,11 +64,27 @@ static void test_basic_parsing(void) { assert_se(journal_importer_eof(&imp)); } +static void test_bad_input(void) { + _cleanup_(journal_importer_cleanup) JournalImporter imp = {}; + int r; + + imp.fd = open(TEST_DATA_DIR("/journal-data/journal-2.txt"), O_RDONLY|O_CLOEXEC); + assert_se(imp.fd >= 0); + + do + r = journal_importer_process_data(&imp); + while (!journal_importer_eof(&imp)); + assert_se(r == 0); /* If we don't have enough input, 0 is returned */ + + assert_se(journal_importer_eof(&imp)); +} + int main(int argc, char **argv) { log_set_max_level(LOG_DEBUG); log_parse_environment(); test_basic_parsing(); + test_bad_input(); return 0; } diff --git a/test/journal-data/journal-2.txt b/test/journal-data/journal-2.txt new file mode 100644 index 0000000000..4f582a0e88 Binary files /dev/null and b/test/journal-data/journal-2.txt differ -- cgit v1.2.3-54-g00ecf From 5b45a16067d7b8ce12e4732de7cc14b3f804ef06 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 10:06:32 -0500 Subject: coredump: with --backtrace accept a journal entry on stdin The entry must be a single entry in the journal export format, including the terminating double newline. The MESSAGE field is now generated on the sender side. The advantage is that the reporter can easily pass additional metadata. Continuing with the example of the python excepthook: COREDUMP_PYTHON_EXECUTABLE=/usr/bin/python3 COREDUMP_PYTHON_VERSION=3.5.2 (default, Sep 14 2016, 11:28:32) [GCC 6.2.1 20160901 (Red Hat 6.2.1-1)] COREDUMP_PYTHON_THREAD_INFO=sys.thread_info(name='pthread', lock='semaphore', version='NPTL 2.24') COREDUMP_PYTHON_EXCEPTION_TYPE=ZeroDivisionError COREDUMP_PYTHON_EXCEPTION_VALUE=division by zero MESSAGE=Process 29514 (systemd_coredump_exception_handler.py) of user zbyszek failed with ZeroDivisionError: division by zero Traceback (most recent call last): File "systemd_coredump_exception_handler.py", line 134, in g() File "systemd_coredump_exception_handler.py", line 133, in g f() File "systemd_coredump_exception_handler.py", line 131, in f div0 = 1 / 0 ZeroDivisionError: division by zero Local variables in innermost frame: a=3 h= One consideration is whether to use the Journal Export Format, or send packets over a UNIX socket instead. The advantage of current solution is that although parsing is more complicated on the receiver side, it is much easier to use on the sender side. I hope this can be used by various languages for which writing binary structures to a UNIX socket is harder and more likely to be done wrong than piping of a simple textyish format. --- src/coredump/coredump.c | 79 ++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 2d9819e5b0..38ba6e9079 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -820,7 +820,7 @@ static void map_context_fields(const struct iovec *iovec, const char *context[]) static int process_socket(int fd) { _cleanup_close_ int coredump_fd = -1; struct iovec *iovec = NULL; - size_t n_iovec = 0, n_iovec_allocated = 0, i; + size_t n_iovec = 0, n_allocated = 0, i; const char *context[_CONTEXT_MAX] = {}; int r; @@ -845,7 +845,7 @@ static int process_socket(int fd) { ssize_t n; ssize_t l; - if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) { + if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + 3)) { r = log_oom(); goto finish; } @@ -909,7 +909,7 @@ static int process_socket(int fd) { n_iovec++; } - if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) { + if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + 3)) { r = log_oom(); goto finish; } @@ -924,7 +924,7 @@ static int process_socket(int fd) { assert(context[CONTEXT_COMM]); assert(coredump_fd >= 0); - r = submit_coredump(context, iovec, n_iovec_allocated, n_iovec, coredump_fd); + r = submit_coredump(context, iovec, n_allocated, n_iovec, coredump_fd); finish: for (i = 0; i < n_iovec; i++) @@ -1048,7 +1048,8 @@ static int gather_pid_metadata( const char *context[_CONTEXT_MAX], char **comm_fallback, char **comm_ret, - struct iovec iovec[27], size_t *n_iovec) { + struct iovec *iovec, size_t *n_iovec) { + /* We need 25 empty slots in iovec! */ _cleanup_free_ char *exe = NULL, *comm = NULL; uid_t owner_uid; @@ -1237,13 +1238,13 @@ static int process_kernel(int argc, char* argv[]) { static int process_backtrace(int argc, char *argv[]) { const char *context[_CONTEXT_MAX]; - char *t; - _cleanup_free_ char *comm = NULL; - struct iovec iovec[27]; - size_t n_iovec = 0, i, n_to_free; - uint8_t buf[4096]; - ssize_t buf_bytes; + _cleanup_free_ char *comm = NULL, *message = NULL; + _cleanup_free_ struct iovec *iovec = NULL; + size_t n_iovec, n_allocated, n_to_free = 0, i; int r; + JournalImporter importer = { + .fd = STDIN_FILENO, + }; log_debug("Processing backtrace on stdin..."); @@ -1259,38 +1260,50 @@ static int process_backtrace(int argc, char *argv[]) { context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 2]; context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 2]; - r = gather_pid_metadata(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_iovec); + n_allocated = 32; /* 25 metadata, 2 static, +unknown input, rounded up */ + iovec = new(struct iovec, n_allocated); + if (!iovec) + return log_oom(); + + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_to_free); if (r < 0) goto finish; + n_iovec = n_to_free; - if (isempty(context[CONTEXT_SIGNAL])) - context[CONTEXT_SIGNAL] = "an exception"; - - buf_bytes = loop_read(STDIN_FILENO, buf, sizeof(buf) - 1, false); - if (buf_bytes < 0) { - log_error_errno(buf_bytes, "Failed to read backtrace from stdin: %m"); - goto finish; - } - buf[buf_bytes] = '\0'; - - t = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", comm, ")" - " of user ", context[CONTEXT_UID], - " failed with ", context[CONTEXT_SIGNAL], - ":\n\n", buf, NULL); - if (!t) { - log_oom(); - goto finish; + while (true) { + r = journal_importer_process_data(&importer); + if (r < 0) { + log_error_errno(r, "Failed to parse journal entry on stdin: %m"); + goto finish; + } + if (r == 1) + break; } - IOVEC_SET_STRING(iovec[n_iovec++], t); - n_to_free = n_iovec; + if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + importer.iovw.count + 2)) + return log_oom(); + + if (journal_importer_eof(&importer)) { + log_warning("Did not receive a full journal entry on stdin, ignoring message sent by reporter"); - IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95"); + message = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", comm, ")" + " of user ", context[CONTEXT_UID], + " failed with ", context[CONTEXT_SIGNAL]); + if (!message) { + r = log_oom(); + goto finish; + } + IOVEC_SET_STRING(iovec[n_iovec++], message); + } else { + for (i = 0; i < importer.iovw.count; i++) + iovec[n_iovec++] = importer.iovw.iovec[i]; + } + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95"); assert_cc(2 == LOG_CRIT); IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); - assert(n_iovec <= ELEMENTSOF(iovec)); + assert(n_iovec <= n_allocated); r = sd_journal_sendv(iovec, n_iovec); if (r < 0) -- cgit v1.2.3-54-g00ecf From f6940bc34a6128af3f867326d8dd5948e19b4bf5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 10:48:15 -0500 Subject: man: describe systemd-coredump --backtrace --- man/systemd-coredump.xml | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml index 4a1bc8b296..7243467dc2 100644 --- a/man/systemd-coredump.xml +++ b/man/systemd-coredump.xml @@ -52,14 +52,26 @@ /usr/lib/systemd/systemd-coredump + /usr/lib/systemd/systemd-coredump systemd-coredump@.service systemd-coredump.socket Description - systemd-coredump is a system service that can acquire core dumps - from the kernel and handle them in various ways. + systemd-coredump@.service is a system service that can acquire core + dumps from the kernel and handle them in various ways. The systemd-coredump + executable does the actual work. It is invoked twice: once as the handler by the kernel, and the + second time in the systemd-coredump@.service to actually write the data to + the journal. + + When the kernel invokes systemd-coredump to handle a core dump, it runs + in privileged mode, and will connect to the socket created by the + systemd-coredump.socket unit, which in turn will spawn an unprivileged + systemd-coredump@.service instance to process the core dump. Hence + systemd-coredump.socket and systemd-coredump@.service + are helper units which do the actual processing of core dumps and are subject to normal service + management. Core dumps can be written to the journal or saved as a file. Once saved they can be retrieved for further processing, for example in @@ -70,18 +82,20 @@ if possible to the journal and store the core dump itself in an external file in /var/lib/systemd/coredump. - When the kernel invokes systemd-coredump to handle a core dump, - it will connect to the socket created by the systemd-coredump.socket - unit, which in turn will spawn a systemd-coredump@.service instance - to process the core dump. Hence systemd-coredump.socket - and systemd-coredump@.service are helper units which do the actual - processing of core dumps and are subject to normal service management. - The behavior of a specific program upon reception of a signal is governed by a few factors which are described in detail in core5. In particular, the core dump will only be processed when the related resource limits are sufficient. + + It is also possible to invoke systemd-coredump with + option. In this case, systemd-coredump expects + a journal entry in the journal + Journal Export Format + on standard input. The entry should contain a MESSAGE= field and any additional + metadata fields the caller deems reasonable. systemd-coredump will append + additional metadata fields in the same way it does for core dumps received from the kernel. In + this mode, no core dump is stored in the journal. @@ -91,7 +105,8 @@ systemd.exec5. - In order to be used systemd-coredump must be configured in + In order to be used by the kernel to handle core dumps, + systemd-coredump must be configured in sysctl8 parameter kernel.core_pattern. The syntax of this parameter is explained in core5. @@ -99,14 +114,20 @@ kernel.core_pattern accordingly. This file may be masked or overridden to use a different setting following normal sysctl.d5 - rules. - If the sysctl configuration is modified, it must be updated in the kernel before - it takes effect, see + rules. If the sysctl configuration is modified, it must be updated in the kernel before it + takes effect, see sysctl8 and systemd-sysctl8. + In order to by used in the mode, an appropriate backtrace + handler must be installed on the sender side. For example, in case of + python1, this + means a sys.excepthook must installed, see + systemd-coredump-python. + + The behavior of systemd-coredump itself is configured through the configuration file /etc/systemd/coredump.conf and corresponding snippets /etc/systemd/coredump.conf.d/*.conf, see -- cgit v1.2.3-54-g00ecf From 5ab9ed0762ca332634f221c56258ee8e32cdfdc0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 11:29:31 -0500 Subject: coredumpctl: just use argv instead of building a temporary set No functional change, and we don't lose match order. --- src/coredump/coredumpctl.c | 101 ++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 66 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index fcb741b353..612004d7d5 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -38,10 +38,10 @@ #include "parse-util.h" #include "path-util.h" #include "process-util.h" -#include "set.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" +#include "strv.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" @@ -60,36 +60,9 @@ static int arg_no_legend = false; static int arg_one = false; static FILE* arg_output = NULL; static bool arg_reverse = false; +static char** arg_matches = NULL; -static Set *new_matches(void) { - Set *set; - char *tmp; - int r; - - set = set_new(NULL); - if (!set) { - log_oom(); - return NULL; - } - - tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); - if (!tmp) { - log_oom(); - set_free(set); - return NULL; - } - - r = set_consume(set, tmp); - if (r < 0) { - log_error_errno(r, "failed to add to set: %m"); - set_free(set); - return NULL; - } - - return set; -} - -static int add_match(Set *set, const char *match) { +static int add_match(sd_journal *j, const char *match) { _cleanup_free_ char *p = NULL; char *pattern = NULL; const char* prefix; @@ -101,7 +74,8 @@ static int add_match(Set *set, const char *match) { else if (strchr(match, '/')) { r = path_make_absolute_cwd(match, &p); if (r < 0) - goto fail; + return log_error_errno(r, "path_make_absolute_cwd(\"%s\"): %m", match); + match = p; prefix = "COREDUMP_EXE="; } else if (parse_pid(match, &pid) >= 0) @@ -110,19 +84,32 @@ static int add_match(Set *set, const char *match) { prefix = "COREDUMP_COMM="; pattern = strjoin(prefix, match); - if (!pattern) { - r = -ENOMEM; - goto fail; - } + if (!pattern) + return log_oom(); + + log_debug("Adding match: %s", pattern); + r = sd_journal_add_match(j, pattern, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match \"%s\": %m", match); + return 0; +} + +static int add_matches(sd_journal *j) { + char **match; + int r; - log_debug("Adding pattern: %s", pattern); - r = set_consume(set, pattern); + r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0); if (r < 0) - goto fail; + return log_error_errno(r, "Failed to add match \"%s\": %m", + "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); + + STRV_FOREACH(match, arg_matches) { + r = add_match(j, *match); + if (r < 0) + return r; + } return 0; -fail: - return log_error_errno(r, "Failed to add match: %m"); } static void help(void) { @@ -147,14 +134,14 @@ static void help(void) { , program_invocation_short_name); } -static int parse_argv(int argc, char *argv[], Set *matches) { +static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, }; - int r, c; + int c; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, @@ -251,12 +238,8 @@ static int parse_argv(int argc, char *argv[], Set *matches) { return -EINVAL; } - while (optind < argc) { - r = add_match(matches, argv[optind]); - if (r != 0) - return r; - optind++; - } + if (optind < argc) + arg_matches = argv + optind; return 0; } @@ -875,22 +858,13 @@ finish: int main(int argc, char *argv[]) { _cleanup_(sd_journal_closep) sd_journal*j = NULL; - const char* match; - Iterator it; int r = 0; - _cleanup_set_free_free_ Set *matches = NULL; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); - matches = new_matches(); - if (!matches) { - r = -ENOMEM; - goto end; - } - - r = parse_argv(argc, argv, matches); + r = parse_argv(argc, argv); if (r < 0) goto end; @@ -913,14 +887,9 @@ int main(int argc, char *argv[]) { } } - SET_FOREACH(match, matches, it) { - r = sd_journal_add_match(j, match, strlen(match)); - if (r != 0) { - log_error_errno(r, "Failed to add match '%s': %m", - match); - goto end; - } - } + r = add_matches(j); + if (r < 0) + goto end; if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *filter; -- cgit v1.2.3-54-g00ecf From 2b0445262ad9be2a9bf49956ab8e886ea2e48a0a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 12:48:23 -0500 Subject: tree-wide: add SD_ID128_MAKE_STR, remove LOG_MESSAGE_ID Embedding sd_id128_t's in constant strings was rather cumbersome. We had SD_ID128_CONST_STR which returned a const char[], but it had two problems: - it wasn't possible to statically concatanate this array with a normal string - gcc wasn't really able to optimize this, and generated code to perform the "conversion" at runtime. Because of this, even our own code in coredumpctl wasn't using SD_ID128_CONST_STR. Add a new macro to generate a constant string: SD_ID128_MAKE_STR. It is not as elegant as SD_ID128_CONST_STR, because it requires a repetition of the numbers, but in practice it is more convenient to use, and allows gcc to generate smarter code: $ size .libs/systemd{,-logind,-journald}{.old,} text data bss dec hex filename 1265204 149564 4808 1419576 15a938 .libs/systemd.old 1260268 149564 4808 1414640 1595f0 .libs/systemd 246805 13852 209 260866 3fb02 .libs/systemd-logind.old 240973 13852 209 255034 3e43a .libs/systemd-logind 146839 4984 34 151857 25131 .libs/systemd-journald.old 146391 4984 34 151409 24f71 .libs/systemd-journald It is also much easier to check if a certain binary uses a certain MESSAGE_ID: $ strings .libs/systemd.old|grep MESSAGE_ID MESSAGE_ID=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x MESSAGE_ID=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x MESSAGE_ID=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x MESSAGE_ID=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x $ strings .libs/systemd|grep MESSAGE_ID MESSAGE_ID=c7a787079b354eaaa9e77b371893cd27 MESSAGE_ID=b07a249cd024414a82dd00cd181378ff MESSAGE_ID=641257651c1b4ec9a8624d7a40a9e1e7 MESSAGE_ID=de5b426a63be47a7b6ac3eaac82e2f6f MESSAGE_ID=d34d037fff1847e6ae669a370e694725 MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5 MESSAGE_ID=1dee0369c7fc4736b7099b38ecb46ee7 MESSAGE_ID=39f53479d3a045ac8e11786248231fbf MESSAGE_ID=be02cf6855d2428ba40df7e9d022f03d MESSAGE_ID=7b05ebc668384222baa8881179cfda54 MESSAGE_ID=9d1aaa27d60140bd96365438aad20286 --- Makefile-man.am | 5 + man/sd-id128.xml | 15 ++- src/basic/log.c | 2 +- src/basic/log.h | 3 +- src/core/execute.c | 4 +- src/core/job.c | 14 +-- src/core/manager.c | 8 +- src/core/unit.c | 15 ++- src/coredump/coredump.c | 6 +- src/coredump/coredumpctl.c | 6 +- src/journal/journald-kmsg.c | 3 +- src/journal/journald-server.c | 16 ++-- src/journal/journald-server.h | 2 +- src/journal/journald-syslog.c | 3 +- src/journal/journald.c | 6 +- src/login/logind-button.c | 14 +-- src/login/logind-dbus.c | 2 +- src/login/logind-seat.c | 4 +- src/login/logind-session.c | 4 +- src/machine/machine.c | 4 +- src/resolve/resolved-dns-server.c | 2 +- src/resolve/resolved-dns-transaction.c | 2 +- src/resolve/resolved-dns-trust-anchor.c | 2 +- src/sleep/sleep.c | 4 +- src/systemd/sd-id128.h | 3 + src/systemd/sd-messages.h | 158 +++++++++++++++++++++----------- src/timedate/timedated.c | 4 +- 27 files changed, 190 insertions(+), 121 deletions(-) diff --git a/Makefile-man.am b/Makefile-man.am index 6f59658445..e20187d0df 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -240,6 +240,7 @@ MANPAGES_ALIAS += \ man/SD_ID128_FORMAT_STR.3 \ man/SD_ID128_FORMAT_VAL.3 \ man/SD_ID128_MAKE.3 \ + man/SD_ID128_MAKE_STR.3 \ man/SD_ID128_NULL.3 \ man/SD_INFO.3 \ man/SD_JOURNAL_APPEND.3 \ @@ -597,6 +598,7 @@ man/SD_ID128_CONST_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_VAL.3: man/sd-id128.3 man/SD_ID128_MAKE.3: man/sd-id128.3 +man/SD_ID128_MAKE_STR.3: man/sd-id128.3 man/SD_ID128_NULL.3: man/sd-id128.3 man/SD_INFO.3: man/sd-daemon.3 man/SD_JOURNAL_APPEND.3: man/sd_journal_get_fd.3 @@ -1066,6 +1068,9 @@ man/SD_ID128_FORMAT_VAL.html: man/sd-id128.html man/SD_ID128_MAKE.html: man/sd-id128.html $(html-alias) +man/SD_ID128_MAKE_STR.html: man/sd-id128.html + $(html-alias) + man/SD_ID128_NULL.html: man/sd-id128.html $(html-alias) diff --git a/man/sd-id128.xml b/man/sd-id128.xml index 5f24feff8e..2e29cf91cb 100644 --- a/man/sd-id128.xml +++ b/man/sd-id128.xml @@ -47,6 +47,7 @@ sd-id128 sd_id128_t SD_ID128_MAKE + SD_ID128_MAKE_STR SD_ID128_NULL SD_ID128_CONST_STR SD_ID128_FORMAT_STR @@ -113,12 +114,24 @@ SD_ID128_NULL may be used to refer to the 128bit ID consisting of only NUL bytes. + SD_ID128_MAKE_STR() is similar to SD_ID128_MAKE(), but creates a + const char* expression that can be conveniently used in message formats and such: + + #include <stdio.h> +#define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) + +int main(int argc, char **argv) { + puts("Match for coredumps: MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); +} + + + SD_ID128_CONST_STR() may be used to convert constant 128-bit IDs into constant strings for output. The following example code will output the string "fc2e22bc6ee647b6b90729ab34a250b1": int main(int argc, char *argv[]) { - puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); + puts("Match for coredumps: %s", SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); } SD_ID128_FORMAT_STR() and diff --git a/src/basic/log.c b/src/basic/log.c index 1362b1c086..e6d2d61d72 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -1164,7 +1164,7 @@ int log_syntax_internal( return log_struct_internal( level, error, file, line, func, - LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION), + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, "CONFIG_FILE=%s", config_file, "CONFIG_LINE=%u", config_line, LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer), diff --git a/src/basic/log.h b/src/basic/log.h index 2afee20bb5..9cacbb6b70 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -214,9 +214,8 @@ bool log_on_console(void) _pure_; const char *log_target_to_string(LogTarget target) _const_; LogTarget log_target_from_string(const char *s) _pure_; -/* Helpers to prepare various fields for structured logging */ +/* Helper to prepare various field for structured logging */ #define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ -#define LOG_MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x) void log_received_signal(int level, const struct signalfd_siginfo *si); diff --git a/src/core/execute.c b/src/core/execute.c index 4c2968f971..f455afa962 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2981,7 +2981,7 @@ int exec_spawn(Unit *unit, log_open(); if (error_message) log_struct_errno(LOG_ERR, r, - LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "%s: %m", error_message), @@ -2989,7 +2989,7 @@ int exec_spawn(Unit *unit, NULL); else log_struct_errno(LOG_ERR, r, - LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m", exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD), diff --git a/src/core/job.c b/src/core/job.c index 00f7d7998f..d5943d3713 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -744,9 +744,8 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { } static void job_log_status_message(Unit *u, JobType t, JobResult result) { - const char *format; + const char *format, *mid; char buf[LINE_MAX]; - sd_id128_t mid; static const int job_result_log_level[_JOB_RESULT_MAX] = { [JOB_DONE] = LOG_INFO, [JOB_CANCELED] = LOG_INFO, @@ -782,16 +781,19 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { switch (t) { case JOB_START: - mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED; + if (result == JOB_DONE) + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR; + else + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILED_STR; break; case JOB_RELOAD: - mid = SD_MESSAGE_UNIT_RELOADED; + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADED_STR; break; case JOB_STOP: case JOB_RESTART: - mid = SD_MESSAGE_UNIT_STOPPED; + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPED_STR; break; default: @@ -804,7 +806,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { } log_struct(job_result_log_level[result], - LOG_MESSAGE_ID(mid), + mid, LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), "RESULT=%s", job_result_to_string(result), diff --git a/src/core/manager.c b/src/core/manager.c index 5646889a8e..b509adfc64 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2171,7 +2171,7 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint assert(m->time_change_fd == fd); log_struct(LOG_DEBUG, - LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE), + "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR, LOG_MESSAGE("Time has been changed"), NULL); @@ -2930,7 +2930,7 @@ static void manager_notify_finished(Manager *m) { initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, "KERNEL_USEC="USEC_FMT, kernel_usec, "INITRD_USEC="USEC_FMT, initrd_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, @@ -2945,7 +2945,7 @@ static void manager_notify_finished(Manager *m) { initrd_usec = 0; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, "KERNEL_USEC="USEC_FMT, kernel_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s (kernel) + %s (userspace) = %s.", @@ -2959,7 +2959,7 @@ static void manager_notify_finished(Manager *m) { total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_USER_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_USER_STARTUP_FINISHED_STR, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)), diff --git a/src/core/unit.c b/src/core/unit.c index 5e4b1567d8..9221412c48 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1466,9 +1466,8 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { } static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { - const char *format; + const char *format, *mid; char buf[LINE_MAX]; - sd_id128_t mid; assert(u); @@ -1486,9 +1485,9 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { snprintf(buf, sizeof buf, format, unit_description(u)); REENABLE_WARNING; - mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : - t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING : - SD_MESSAGE_UNIT_RELOADING; + mid = t == JOB_START ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTING_STR : + t == JOB_STOP ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPING_STR : + "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADING_STR; /* Note that we deliberately use LOG_MESSAGE() instead of * LOG_UNIT_MESSAGE() here, since this is supposed to mimic @@ -1497,7 +1496,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { * possible, which means we should avoid the low-level unit * name. */ log_struct(LOG_INFO, - LOG_MESSAGE_ID(mid), + mid, LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), NULL); @@ -4036,7 +4035,7 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) { } log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where), "WHERE=%s", where, @@ -4058,7 +4057,7 @@ int unit_fail_if_symlink(Unit *u, const char* where) { return 0; log_struct(LOG_ERR, - LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Mount on symlink %s not allowed.", where), "WHERE=%s", where, diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 38ba6e9079..7b11e230bf 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -360,7 +360,7 @@ static int save_external_coredump( log_struct(LOG_INFO, LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size), "SIZE_LIMIT=%zu", max_size, - LOG_MESSAGE_ID(SD_MESSAGE_TRUNCATED_CORE), + "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR, NULL); if (fstat(fd, &st) < 0) { @@ -1220,7 +1220,7 @@ static int process_kernel(int argc, char* argv[]) { goto finish; n_iovec = n_to_free; - IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); assert_cc(2 == LOG_CRIT); IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); @@ -1299,7 +1299,7 @@ static int process_backtrace(int argc, char *argv[]) { iovec[n_iovec++] = importer.iovw.iovec[i]; } - IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95"); + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR); assert_cc(2 == LOG_CRIT); IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 612004d7d5..439ea6964e 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -25,6 +25,7 @@ #include #include "sd-journal.h" +#include "sd-messages.h" #include "alloc-util.h" #include "compress.h" @@ -98,10 +99,9 @@ static int add_matches(sd_journal *j) { char **match; int r; - r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0); + r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR, 0); if (r < 0) - return log_error_errno(r, "Failed to add match \"%s\": %m", - "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); + return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); STRV_FOREACH(match, arg_matches) { r = add_match(j, *match); diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 18c8644507..8afaec0ced 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -156,7 +156,8 @@ static void dev_kmsg_record(Server *s, const char *p, size_t l) { /* Did we lose any? */ if (serial > *s->kernel_seqnum) - server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, + server_driver_message(s, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_MISSED_STR, LOG_MESSAGE("Missed %"PRIu64" kernel messages", serial - *s->kernel_seqnum), NULL); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 8b92ea3def..451f16483f 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -214,7 +214,7 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { format_bytes(fb5, sizeof(fb5), storage->space.limit); format_bytes(fb6, sizeof(fb6), storage->space.available); - server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, + server_driver_message(s, "MESSAGE_ID=" SD_MESSAGE_JOURNAL_USAGE_STR, LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", storage->name, storage->path, fb1, fb5, fb6), "JOURNAL_NAME=%s", storage->name, @@ -1061,8 +1061,7 @@ static void dispatch_message_real( write_to_journal(s, journal_uid, iovec, n, priority); } -void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) { - char mid[11 + 32 + 1]; +void server_driver_message(Server *s, const char *message_id, const char *format, ...) { struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS]; unsigned n = 0, m; int r; @@ -1080,11 +1079,8 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, assert_cc(6 == LOG_INFO); IOVEC_SET_STRING(iovec[n++], "PRIORITY=6"); - if (!sd_id128_is_null(message_id)) { - snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id)); - IOVEC_SET_STRING(iovec[n++], mid); - } - + if (message_id) + IOVEC_SET_STRING(iovec[n++], message_id); m = n; va_start(ap, format); @@ -1174,7 +1170,7 @@ void server_dispatch_message( /* Write a suppression message if we suppressed something */ if (rl > 1) - server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, + server_driver_message(s, "MESSAGE_ID=" SD_MESSAGE_JOURNAL_DROPPED_STR, LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, path), NULL); @@ -1273,7 +1269,7 @@ finish: sd_journal_close(j); - server_driver_message(s, SD_ID128_NULL, + server_driver_message(s, NULL, LOG_MESSAGE("Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n), diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 716e758b7c..75ac114d24 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -176,7 +176,7 @@ struct Server { #define N_IOVEC_PAYLOAD_FIELDS 15 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); -void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_; +void server_driver_message(Server *s, const char *message_id, const char *format, ...) _printf_(3,0) _sentinel_; /* gperf lookup function */ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length); diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 896303fb85..474369039a 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -444,7 +444,8 @@ void server_maybe_warn_forward_syslog_missed(Server *s) { if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) return; - server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, + server_driver_message(s, + "MESSAGE_ID=" SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR, LOG_MESSAGE("Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed), NULL); diff --git a/src/journal/journald.c b/src/journal/journald.c index 54fd1f999d..1aaef387b4 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -56,7 +56,8 @@ int main(int argc, char *argv[]) { server_flush_dev_kmsg(&server); log_debug("systemd-journald running as pid "PID_FMT, getpid()); - server_driver_message(&server, SD_MESSAGE_JOURNAL_START, + server_driver_message(&server, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_START_STR, LOG_MESSAGE("Journal started"), NULL); @@ -114,7 +115,8 @@ int main(int argc, char *argv[]) { } log_debug("systemd-journald stopped as pid "PID_FMT, getpid()); - server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, + server_driver_message(&server, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_STOP_STR, LOG_MESSAGE("Journal stopped"), NULL); diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 90fb93bbaf..d739af8ea2 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -155,7 +155,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u case KEY_POWER2: log_struct(LOG_INFO, LOG_MESSAGE("Power key pressed."), - LOG_MESSAGE_ID(SD_MESSAGE_POWER_KEY), + "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR, NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); @@ -170,7 +170,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u case KEY_SLEEP: log_struct(LOG_INFO, LOG_MESSAGE("Suspend key pressed."), - LOG_MESSAGE_ID(SD_MESSAGE_SUSPEND_KEY), + "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR, NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); @@ -179,7 +179,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u case KEY_SUSPEND: log_struct(LOG_INFO, LOG_MESSAGE("Hibernate key pressed."), - LOG_MESSAGE_ID(SD_MESSAGE_HIBERNATE_KEY), + "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR, NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); @@ -191,7 +191,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u if (ev.code == SW_LID) { log_struct(LOG_INFO, LOG_MESSAGE("Lid closed."), - LOG_MESSAGE_ID(SD_MESSAGE_LID_CLOSED), + "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR, NULL); b->lid_closed = true; @@ -201,7 +201,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u } else if (ev.code == SW_DOCK) { log_struct(LOG_INFO, LOG_MESSAGE("System docked."), - LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_DOCKED), + "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR, NULL); b->docked = true; @@ -212,7 +212,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u if (ev.code == SW_LID) { log_struct(LOG_INFO, LOG_MESSAGE("Lid opened."), - LOG_MESSAGE_ID(SD_MESSAGE_LID_OPENED), + "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR, NULL); b->lid_closed = false; @@ -221,7 +221,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u } else if (ev.code == SW_DOCK) { log_struct(LOG_INFO, LOG_MESSAGE("System undocked."), - LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_UNDOCKED), + "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR, NULL); b->docked = false; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ad44ca290e..c6be596af3 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1430,7 +1430,7 @@ static int bus_manager_log_shutdown( p = strjoina(p, " (", m->wall_message, ")."); return log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, p, q, NULL); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index bfbd07309d..e4836fcaab 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -416,7 +416,7 @@ int seat_start(Seat *s) { return 0; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SEAT_START), + "MESSAGE_ID=" SD_MESSAGE_SEAT_START_STR, "SEAT_ID=%s", s->id, LOG_MESSAGE("New seat %s.", s->id), NULL); @@ -444,7 +444,7 @@ int seat_stop(Seat *s, bool force) { if (s->started) log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SEAT_STOP), + "MESSAGE_ID=" SD_MESSAGE_SEAT_STOP_STR, "SEAT_ID=%s", s->id, LOG_MESSAGE("Removed seat %s.", s->id), NULL); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index fd7fcf7f2c..4a168906d6 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -561,7 +561,7 @@ int session_start(Session *s) { return r; log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START), + "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR, "SESSION_ID=%s", s->id, "USER_ID=%s", s->user->name, "LEADER="PID_FMT, s->leader, @@ -666,7 +666,7 @@ int session_finalize(Session *s) { if (s->started) log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP), + "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR, "SESSION_ID=%s", s->id, "USER_ID=%s", s->user->name, "LEADER="PID_FMT, s->leader, diff --git a/src/machine/machine.c b/src/machine/machine.c index eb4b35d52a..067a7e2866 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -401,7 +401,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) { return r; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_MACHINE_START), + "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR, "NAME=%s", m->name, "LEADER="PID_FMT, m->leader, LOG_MESSAGE("New machine %s.", m->name), @@ -464,7 +464,7 @@ int machine_finalize(Machine *m) { if (m->started) log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_MACHINE_STOP), + "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR, "NAME=%s", m->name, "LEADER="PID_FMT, m->leader, LOG_MESSAGE("Machine %s terminated.", m->name), diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 10562d03ec..072cbfca1a 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -570,7 +570,7 @@ void dns_server_warn_downgrade(DnsServer *server) { return; log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_DOWNGRADE), + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_DOWNGRADE_STR, LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)), "DNS_SERVER=%s", dns_server_string(server), "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level), diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 69e1d58ccf..9687409663 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -318,7 +318,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { dns_resource_key_to_string(t->key, key_str, sizeof key_str); log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_FAILURE), + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR, LOG_MESSAGE("DNSSEC validation failed for question %s: %s", key_str, dnssec_result_to_string(t->answer_dnssec_result)), "DNS_TRANSACTION=%" PRIu16, t->id, "DNS_QUESTION=%s", key_str, diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index 9917b9e984..d8529f8317 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -594,7 +594,7 @@ static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord /* We found the key! Warn the user */ log_struct(LOG_WARNING, - LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED), + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR, LOG_MESSAGE("DNSSEC Trust anchor %s has been revoked. Please update the trust anchor, or upgrade your operating system."), strna(dns_resource_record_to_string(rr)), "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr), NULL); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index c8f0742183..ea96615222 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -109,7 +109,7 @@ static int execute(char **modes, char **states) { execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments); log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), + "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, LOG_MESSAGE("Suspending system..."), "SLEEP=%s", arg_verb, NULL); @@ -119,7 +119,7 @@ static int execute(char **modes, char **states) { return r; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP), + "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, LOG_MESSAGE("System resumed."), "SLEEP=%s", arg_verb, NULL); diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h index 6cc8e4ac0e..9b38969b77 100644 --- a/src/systemd/sd-id128.h +++ b/src/systemd/sd-id128.h @@ -100,6 +100,9 @@ int sd_id128_get_invocation(sd_id128_t *ret); ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \ 0 }) +#define SD_ID128_MAKE_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \ + #a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p + _sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) { return memcmp(&a, &b, 16) == 0; } diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index 542e900744..f466d9b062 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -33,61 +33,109 @@ _SD_BEGIN_DECLARATIONS; * with journalctl --new-id128. Do not use any other IDs, and do not * count them up manually. */ -#define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) -#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) -#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) -#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) -#define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) - -#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) -#define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) -#define SD_MESSAGE_BACKTRACE SD_ID128_MAKE(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) - -#define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) -#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) -#define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) -#define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) -#define SD_MESSAGE_MACHINE_START SD_ID128_MAKE(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) -#define SD_MESSAGE_MACHINE_STOP SD_ID128_MAKE(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) - -#define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) -#define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) - -#define SD_MESSAGE_STARTUP_FINISHED SD_ID128_MAKE(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) -#define SD_MESSAGE_USER_STARTUP_FINISHED SD_ID128_MAKE(ee,d0,0a,68,ff,d8,4e,31,88,21,05,fd,97,3a,bd,d1) - -#define SD_MESSAGE_SLEEP_START SD_ID128_MAKE(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) -#define SD_MESSAGE_SLEEP_STOP SD_ID128_MAKE(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) - -#define SD_MESSAGE_SHUTDOWN SD_ID128_MAKE(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) - -#define SD_MESSAGE_UNIT_STARTING SD_ID128_MAKE(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) -#define SD_MESSAGE_UNIT_STARTED SD_ID128_MAKE(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) -#define SD_MESSAGE_UNIT_STOPPING SD_ID128_MAKE(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) -#define SD_MESSAGE_UNIT_STOPPED SD_ID128_MAKE(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) -#define SD_MESSAGE_UNIT_FAILED SD_ID128_MAKE(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) -#define SD_MESSAGE_UNIT_RELOADING SD_ID128_MAKE(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) -#define SD_MESSAGE_UNIT_RELOADED SD_ID128_MAKE(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) - -#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) - -#define SD_MESSAGE_FORWARD_SYSLOG_MISSED SD_ID128_MAKE(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) - -#define SD_MESSAGE_OVERMOUNTING SD_ID128_MAKE(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) - -#define SD_MESSAGE_LID_OPENED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) -#define SD_MESSAGE_LID_CLOSED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) -#define SD_MESSAGE_SYSTEM_DOCKED SD_ID128_MAKE(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) -#define SD_MESSAGE_SYSTEM_UNDOCKED SD_ID128_MAKE(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) -#define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) -#define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) -#define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) - -#define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) - -#define SD_MESSAGE_DNSSEC_FAILURE SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) -#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) -#define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) +#define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) +#define SD_MESSAGE_JOURNAL_START_STR SD_ID128_MAKE_STR(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) +#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) +#define SD_MESSAGE_JOURNAL_STOP_STR SD_ID128_MAKE_STR(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) +#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_JOURNAL_DROPPED_STR SD_ID128_MAKE_STR(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) +#define SD_MESSAGE_JOURNAL_MISSED_STR SD_ID128_MAKE_STR(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) +#define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) +#define SD_MESSAGE_JOURNAL_USAGE_STR SD_ID128_MAKE_STR(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) + +#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) +#define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) +#define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_TRUNCATED_CORE_STR SD_ID128_MAKE_STR(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_BACKTRACE SD_ID128_MAKE(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) +#define SD_MESSAGE_BACKTRACE_STR SD_ID128_MAKE_STR(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) + +#define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) +#define SD_MESSAGE_SESSION_START_STR SD_ID128_MAKE_STR(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) +#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) +#define SD_MESSAGE_SESSION_STOP_STR SD_ID128_MAKE_STR(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) +#define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) +#define SD_MESSAGE_SEAT_START_STR SD_ID128_MAKE_STR(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) +#define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) +#define SD_MESSAGE_SEAT_STOP_STR SD_ID128_MAKE_STR(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) +#define SD_MESSAGE_MACHINE_START SD_ID128_MAKE(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) +#define SD_MESSAGE_MACHINE_START_STR SD_ID128_MAKE_STR(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) +#define SD_MESSAGE_MACHINE_STOP SD_ID128_MAKE(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) +#define SD_MESSAGE_MACHINE_STOP_STR SD_ID128_MAKE_STR(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) + +#define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) +#define SD_MESSAGE_TIME_CHANGE_STR SD_ID128_MAKE_STR(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) +#define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) +#define SD_MESSAGE_TIMEZONE_CHANGE_STR SD_ID128_MAKE_STR(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) + +#define SD_MESSAGE_STARTUP_FINISHED SD_ID128_MAKE(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) +#define SD_MESSAGE_STARTUP_FINISHED_STR SD_ID128_MAKE_STR(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) +#define SD_MESSAGE_USER_STARTUP_FINISHED \ + SD_ID128_MAKE(ee,d0,0a,68,ff,d8,4e,31,88,21,05,fd,97,3a,bd,d1) +#define SD_MESSAGE_USER_STARTUP_FINISHED_STR \ + SD_ID128_MAKE_STR(ee,d0,0a,68,ff,d8,4e,31,88,21,05,fd,97,3a,bd,d1) + +#define SD_MESSAGE_SLEEP_START SD_ID128_MAKE(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) +#define SD_MESSAGE_SLEEP_START_STR SD_ID128_MAKE_STR(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) +#define SD_MESSAGE_SLEEP_STOP SD_ID128_MAKE(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) +#define SD_MESSAGE_SLEEP_STOP_STR SD_ID128_MAKE_STR(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) + +#define SD_MESSAGE_SHUTDOWN SD_ID128_MAKE(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) +#define SD_MESSAGE_SHUTDOWN_STR SD_ID128_MAKE_STR(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) + +#define SD_MESSAGE_UNIT_STARTING SD_ID128_MAKE(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) +#define SD_MESSAGE_UNIT_STARTING_STR SD_ID128_MAKE_STR(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) +#define SD_MESSAGE_UNIT_STARTED SD_ID128_MAKE(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) +#define SD_MESSAGE_UNIT_STARTED_STR SD_ID128_MAKE_STR(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) +#define SD_MESSAGE_UNIT_STOPPING SD_ID128_MAKE(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) +#define SD_MESSAGE_UNIT_STOPPING_STR SD_ID128_MAKE_STR(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) +#define SD_MESSAGE_UNIT_STOPPED SD_ID128_MAKE(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) +#define SD_MESSAGE_UNIT_STOPPED_STR SD_ID128_MAKE_STR(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) +#define SD_MESSAGE_UNIT_FAILED SD_ID128_MAKE(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) +#define SD_MESSAGE_UNIT_FAILED_STR SD_ID128_MAKE_STR(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) +#define SD_MESSAGE_UNIT_RELOADING SD_ID128_MAKE(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) +#define SD_MESSAGE_UNIT_RELOADING_STR SD_ID128_MAKE_STR(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) +#define SD_MESSAGE_UNIT_RELOADED SD_ID128_MAKE(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) +#define SD_MESSAGE_UNIT_RELOADED_STR SD_ID128_MAKE_STR(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) + +#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) +#define SD_MESSAGE_SPAWN_FAILED_STR SD_ID128_MAKE_STR(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) + +#define SD_MESSAGE_FORWARD_SYSLOG_MISSED SD_ID128_MAKE(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) +#define SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR \ + SD_ID128_MAKE_STR(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) + +#define SD_MESSAGE_OVERMOUNTING SD_ID128_MAKE(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) +#define SD_MESSAGE_OVERMOUNTING_STR SD_ID128_MAKE_STR(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) + +#define SD_MESSAGE_LID_OPENED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) +#define SD_MESSAGE_LID_OPENED_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) +#define SD_MESSAGE_LID_CLOSED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) +#define SD_MESSAGE_LID_CLOSED_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) +#define SD_MESSAGE_SYSTEM_DOCKED SD_ID128_MAKE(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) +#define SD_MESSAGE_SYSTEM_DOCKED_STR SD_ID128_MAKE_STR(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) +#define SD_MESSAGE_SYSTEM_UNDOCKED SD_ID128_MAKE(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) +#define SD_MESSAGE_SYSTEM_UNDOCKED_STR SD_ID128_MAKE_STR(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) +#define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) +#define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) +#define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) +#define SD_MESSAGE_SUSPEND_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) +#define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) +#define SD_MESSAGE_HIBERNATE_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) + +#define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) +#define SD_MESSAGE_INVALID_CONFIGURATION_STR \ + SD_ID128_MAKE_STR(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) + +#define SD_MESSAGE_DNSSEC_FAILURE SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) +#define SD_MESSAGE_DNSSEC_FAILURE_STR SD_ID128_MAKE_STR(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) +#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED \ + SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) +#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR \ + SD_ID128_MAKE_STR(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) +#define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) +#define SD_MESSAGE_DNSSEC_DOWNGRADE_STR SD_ID128_MAKE_STR(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) _SD_END_DECLARATIONS; diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 490929e93b..1061b094d3 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -413,7 +413,7 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error * } log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE), + "MESSAGE_ID=" SD_MESSAGE_TIMEZONE_CHANGE_STR, "TIMEZONE=%s", c->zone, LOG_MESSAGE("Changed time zone to '%s'.", c->zone), NULL); @@ -591,7 +591,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro clock_set_hwclock(tm); log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE), + "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR, "REALTIME="USEC_FMT, timespec_load(&ts), LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec)), NULL); -- cgit v1.2.3-54-g00ecf From a7581ff940b65df9e18ab9ab941a22c8d67b250d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 6 Nov 2016 13:34:31 -0500 Subject: coredumpctl: display non-coredump coredump entries too $ ./coredumpctl --no-pager -1 TIME PID UID GID SIG COREFILE EXE Sun 2016-11-06 10:10:51 EST 29514 1002 1002 - - /usr/bin/python3.5 $ ./coredumpctl info 29514 PID: 29514 (python3) UID: 1002 (zbyszek) GID: 1002 (zbyszek) Reason: ZeroDivisionError Timestamp: Sun 2016-11-06 10:10:51 EST (3h 22min ago) Command Line: python3 systemd_coredump_exception_handler.py Executable: /usr/bin/python3.5 Control Group: /user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service Unit: user@1002.service User Unit: gnome-terminal-server.service Slice: user-1002.slice Owner UID: 1002 (zbyszek) Boot ID: 1531fd22ec84429e85ae888b12fadb91 Machine ID: 519a16632fbd4c71966ce9305b360c9c Hostname: laptop Storage: none Message: Process 29514 (systemd_coredump_exception_handler.py) of user zbyszek failed with ZeroDivisionError: division by Traceback (most recent call last): File "systemd_coredump_exception_handler.py", line 134, in g() File "systemd_coredump_exception_handler.py", line 133, in g f() File "systemd_coredump_exception_handler.py", line 131, in f div0 = 1 / 0 ZeroDivisionError: division by zero Local variables in innermost frame: a=3 h= --- src/coredump/coredumpctl.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 439ea6964e..6abd99430b 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -103,6 +103,10 @@ static int add_matches(sd_journal *j) { if (r < 0) return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); + r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR); + STRV_FOREACH(match, arg_matches) { r = add_match(j, *match); if (r < 0) @@ -312,7 +316,7 @@ static int print_field(FILE* file, sd_journal *j) { static int print_list(FILE* file, sd_journal *j, int had_legend) { _cleanup_free_ char - *pid = NULL, *uid = NULL, *gid = NULL, + *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL, *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, *filename = NULL, *coredump = NULL; const void *d; @@ -321,11 +325,13 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { char buf[FORMAT_TIMESTAMP_MAX]; int r; const char *present; + bool normal_coredump; assert(file); assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { + RETRIEVE(d, l, "MESSAGE_ID", mid); RETRIEVE(d, l, "COREDUMP_PID", pid); RETRIEVE(d, l, "COREDUMP_UID", uid); RETRIEVE(d, l, "COREDUMP_GID", gid); @@ -358,6 +364,8 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { 8, "COREFILE", "EXE"); + normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR); + if (filename) if (access(filename, R_OK) == 0) present = "present"; @@ -367,15 +375,17 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { present = "error"; else if (coredump) present = "journal"; - else + else if (normal_coredump) present = "none"; + else + present = "-"; fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n", FORMAT_TIMESTAMP_WIDTH, buf, 6, strna(pid), 5, strna(uid), 5, strna(gid), - 3, strna(sgnl), + 3, normal_coredump ? strna(sgnl) : "-", 8, present, strna(exe ?: (comm ?: cmdline))); @@ -384,7 +394,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { static int print_info(FILE *file, sd_journal *j, bool need_space) { _cleanup_free_ char - *pid = NULL, *uid = NULL, *gid = NULL, + *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL, *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, *unit = NULL, *user_unit = NULL, *session = NULL, *boot_id = NULL, *machine_id = NULL, *hostname = NULL, @@ -393,12 +403,14 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { *coredump = NULL; const void *d; size_t l; + bool normal_coredump; int r; assert(file); assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { + RETRIEVE(d, l, "MESSAGE_ID", mid); RETRIEVE(d, l, "COREDUMP_PID", pid); RETRIEVE(d, l, "COREDUMP_UID", uid); RETRIEVE(d, l, "COREDUMP_GID", gid); @@ -424,6 +436,8 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { if (need_space) fputs("\n", file); + normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR); + if (comm) fprintf(file, " PID: %s%s%s (%s)\n", @@ -469,11 +483,12 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { if (sgnl) { int sig; + const char *name = normal_coredump ? "Signal" : "Reason"; - if (safe_atoi(sgnl, &sig) >= 0) - fprintf(file, " Signal: %s (%s)\n", sgnl, signal_to_string(sig)); + if (normal_coredump && safe_atoi(sgnl, &sig) >= 0) + fprintf(file, " %s: %s (%s)\n", name, sgnl, signal_to_string(sig)); else - fprintf(file, " Signal: %s\n", sgnl); + fprintf(file, " %s: %s\n", name, sgnl); } if (timestamp) { -- cgit v1.2.3-54-g00ecf From 561eede4d126610ee5023098fc2787bd8864f144 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 15 Jan 2017 20:25:35 -0500 Subject: coredump: add note about lack of rollback on oom --- src/coredump/coredump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 7b11e230bf..1bb1dbbe8d 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -1049,7 +1049,9 @@ static int gather_pid_metadata( char **comm_fallback, char **comm_ret, struct iovec *iovec, size_t *n_iovec) { - /* We need 25 empty slots in iovec! */ + /* We need 25 empty slots in iovec! + * Note that if we fail on oom later on, we do not roll-back changes to the iovec + * structure. (It remains valid, with the first n_iovec fields initialized.) */ _cleanup_free_ char *exe = NULL, *comm = NULL; uid_t owner_uid; -- cgit v1.2.3-54-g00ecf