[META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
[META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=",
[META_ARGV_PIDFD] = "COREDUMP_BY_PIDFD=",
+ [META_ARGV_TID] = "COREDUMP_TID=",
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
[META_PROC_AUXV] = "COREDUMP_PROC_AUXV=",
+ [META_THREAD_NAME] = "COREDUMP_THREAD_NAME=",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(metadata_field, MetadataField);
free(context->exe);
free(context->unit);
free(context->auxv);
+ free(context->thread_name);
safe_close(context->mount_tree_fd);
iovw_done_free(&context->iovw);
safe_close(context->input_fd);
if (r < 0)
return log_error_errno(r, "Failed to add COREDUMP_COMM= field: %m");
+ if (context->tid > 0)
+ (void) iovw_put_string_fieldf(&context->iovw, "COREDUMP_TID=", PID_FMT, context->tid);
+
+ if (context->thread_name)
+ (void) iovw_put_string_field(&context->iovw, "COREDUMP_THREAD_NAME=", context->thread_name);
+
if (context->exe)
(void) iovw_put_string_field(&context->iovw, "COREDUMP_EXE=", context->exe);
if (r < 0)
return log_error_errno(r, "Failed to get COMM: %m");
+ if (context->tid > 0) {
+ r = pid_get_comm(context->tid, &context->thread_name);
+ if (r < 0)
+ log_warning_errno(r, "Failed to get comm for thread "PID_FMT", ignoring: %m", context->tid);
+ }
+
r = get_process_exe(pid, &context->exe);
if (r < 0)
log_warning_errno(r, "Failed to get EXE, ignoring: %m");
context->got_pidfd = 1;
return 0;
}
+ case META_ARGV_TID:
+ r = parse_pid(s, &context->tid);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse TID \"%s\", ignoring: %m", s);
+ return 0;
+
case META_COMM:
return free_and_strdup_warn(&context->comm, s);
case META_UNIT:
return free_and_strdup_warn(&context->unit, s);
+ case META_THREAD_NAME:
+ return free_and_strdup_warn(&context->thread_name, s);
+
case META_PROC_AUXV: {
char *t = memdup_suffix0(s, size);
if (!t)
META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */
META_ARGV_DUMPABLE, /* %d: as set by the kernel */
META_ARGV_PIDFD, /* %F: pidfd of the process, since v6.16 */
+ META_ARGV_TID, /* %I: TID of the crashing thread, as seen in the initial pid namespace */
/* If new fields are added, they should be added here, to maintain compatibility
* with callers which don't know about the new fields. */
_META_ARGV_MAX,
META_EXE,
META_UNIT,
META_PROC_AUXV,
+ META_THREAD_NAME,
_META_MAX,
_META_INVALID = -EINVAL,
} MetadataField;
uint64_t rlimit; /* META_ARGV_RLIMIT */
char *hostname; /* META_ARGV_HOSTNAME */
unsigned dumpable; /* META_ARGV_DUMPABLE */
+ pid_t tid; /* META_ARGV_TID */
char *comm; /* META_COMM */
char *exe; /* META_EXE */
char *unit; /* META_UNIT */
char *auxv; /* META_PROC_AUXV */
size_t auxv_size; /* META_PROC_AUXV */
+ char *thread_name; /* META_THREAD_NAME */
bool got_pidfd; /* META_ARGV_PIDFD */
bool same_pidns;
bool forwarded;
RET_GATHER(r, fix_xattr_one(fd, "user.coredump.hostname", context->hostname));
RET_GATHER(r, fix_xattr_one(fd, "user.coredump.comm", context->comm));
RET_GATHER(r, fix_xattr_one(fd, "user.coredump.exe", context->exe));
+ if (context->tid > 0) {
+ RET_GATHER(r, fix_xattr_format(fd, "user.coredump.tid", PID_FMT, context->tid));
+ RET_GATHER(r, fix_xattr_one(fd, "user.coredump.thread_name", context->thread_name));
+ }
return r;
}
*slice = NULL, *cgroup = NULL, *owner_uid = NULL,
*message = NULL, *timestamp = NULL, *filename = NULL,
*truncated = NULL, *coredump = NULL,
- *pkgmeta_name = NULL, *pkgmeta_version = NULL, *pkgmeta_json = NULL;
+ *pkgmeta_name = NULL, *pkgmeta_version = NULL, *pkgmeta_json = NULL,
+ *tid = NULL, *thread_name = NULL;
const void *d;
size_t l;
bool normal_coredump;
RETRIEVE(d, l, "COREDUMP_PACKAGE_NAME", pkgmeta_name);
RETRIEVE(d, l, "COREDUMP_PACKAGE_VERSION", pkgmeta_version);
RETRIEVE(d, l, "COREDUMP_PACKAGE_JSON", pkgmeta_json);
+ RETRIEVE(d, l, "COREDUMP_TID", tid);
+ RETRIEVE(d, l, "COREDUMP_THREAD_NAME", thread_name);
RETRIEVE(d, l, "_BOOT_ID", boot_id);
RETRIEVE(d, l, "_MACHINE_ID", machine_id);
RETRIEVE(d, l, "MESSAGE", message);
" PID: %s%s%s\n",
ansi_highlight(), strna(pid), ansi_normal());
+ if (tid) {
+ if (thread_name)
+ fprintf(file, " TID: %s (%s)\n", tid, thread_name);
+ else
+ fprintf(file, " TID: %s\n", tid);
+ }
+
if (uid) {
uid_t n;
# the core dump.
#
# See systemd-coredump(8) and core(5).
-kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d %F
+kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d %F %I
# Allow 16 coredumps to be dispatched in parallel by the kernel.
# We collect metadata from /proc/%P/, and thus need to make sure the crashed
coredumpctl info COREDUMP_EXE="$CORE_TEST_BIN"
coredumpctl info COREDUMP_EXE=aaaaa COREDUMP_EXE= COREDUMP_EXE="$CORE_TEST_BIN"
+# Check that COREDUMP_TID= is present and displayed by coredumpctl info
+coredumpctl info "$CORE_TEST_BIN" | grep "TID:" >/dev/null
+# Check the field is queryable in the journal
+coredumpctl -F COREDUMP_TID
+
coredumpctl debug --debugger=/bin/true "$CORE_TEST_BIN"
SYSTEMD_DEBUGGER=/bin/true coredumpctl debug "$CORE_TEST_BIN"
coredumpctl debug --debugger=/bin/true --debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_BIN##*/}"