From: jolsa@redhat.com
To: mingo@elte.hu, rostedt@goodmis.org
Cc: linux-kernel@vger.kernel.org
Subject: [RFC PATCH 1/2] tracing - signal tracer
Date: Mon, 14 Sep 2009 12:14:10 +0200 [thread overview]
Message-ID: <1252923251-6735-2-git-send-email-jolsa@redhat.com> (raw)
In-Reply-To: <1252923251-6735-1-git-send-email-jolsa@redhat.com>
Implements the tracer for the signals. It is possible to narrow the trace
using the "set_ftrace_pid" pid filter file.
Usage (running some of the pthread-tests pkg's binaries):
sh-4.0# echo signal > current_tracer
sh-4.0# /tests/signal-loss
sh-4.0# /tests/ptrace_event_clone
sh-4.0# /tests/ptrace-on-job-control-stopped
sh-4.0# /tests/clone-ptrace
sh-4.0# cat trace
# tracer: signal
#
# TIMESTAMP CPU# FROM-PID TO-PID SIGNAL-NUM
# | | | | | | | |
217.117000 [000] modprobe-8741 khelper-8740 SIGCHLD-17
217.142000 [001] signal-loss-8742 signal-loss-8743 SIGSTOP-19
217.143000 [001] signal-loss-8742 signal-loss-8743 SIGINT-2
218.145000 [001] <idle>-0 signal-loss-8742 SIGALRM-14
218.149000 [001] signal-loss-8742 signal-loss-8743 SIGKILL-9
218.159000 [001] signal-loss-8742 sh-283 SIGCHLD-17
221.108000 [001] modprobe-8745 khelper-8744 SIGCHLD-17
221.145000 [001] cat-8746 sh-283 SIGCHLD-17
254.790000 [000] modprobe-8748 khelper-8747 SIGCHLD-17
254.820000 [001] ptrace_event_cl-8750 ptrace_event_cl-8750 SIGSTOP-19
254.824000 [001] ptrace_event_cl-8749 ptrace_event_cl-8750 SIGKILL-9
254.824000 [001] ptrace_event_cl-8749 ptrace_event_cl-8751 SIGKILL-9
254.827000 [001] ptrace_event_cl-8749 sh-283 SIGCHLD-17
256.399000 [000] modprobe-8753 khelper-8752 SIGCHLD-17
256.448000 [000] cat-8754 sh-283 SIGCHLD-17
333.634000 [000] modprobe-8756 khelper-8755 SIGCHLD-17
333.663000 [000] ptrace-on-job-c-8757 ptrace-on-job-c-8758 SIGSTOP-19
333.664000 [000] ptrace-on-job-c-8757 ptrace-on-job-c-8758 SIGKILL-9
333.666000 [000] ptrace-on-job-c-8757 init-1 SIGCHLD-17
333.666000 [000] ptrace-on-job-c-8757 sh-283 SIGCHLD-17
335.323000 [000] modprobe-8760 khelper-8759 SIGCHLD-17
448.054000 [001] clone-ptrace-8808 clone-ptrace-8808 SIGSTOP-19
448.057000 [001] clone-ptrace-8807 clone-ptrace-8808 SIGKILL-9
448.058000 [001] clone-ptrace-8807 clone-ptrace-8809 SIGKILL-9
448.063000 [001] clone-ptrace-8807 init-1 SIGCHLD-17
448.063000 [001] clone-ptrace-8807 sh-283 SIGCHLD-17
448.064000 [000] clone-ptrace-8809 clone-ptrace-8809 SIGTRAP-5
448.066000 [000] clone-ptrace-8809 init-1 SIGCHLD-17
449.321000 [001] modprobe-8811 khelper-8810 SIGCHLD-17
sh-4.0#
wbr,
jirka
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
include/linux/signaltrace.h | 22 +++++++
include/linux/tracehook.h | 14 +++++
kernel/signal.c | 3 +
kernel/trace/Kconfig | 11 ++++
kernel/trace/Makefile | 1 +
kernel/trace/trace.h | 9 +++
kernel/trace/trace_signal.c | 132 +++++++++++++++++++++++++++++++++++++++++++
7 files changed, 192 insertions(+), 0 deletions(-)
create mode 100644 include/linux/signaltrace.h
create mode 100644 kernel/trace/trace_signal.c
diff --git a/include/linux/signaltrace.h b/include/linux/signaltrace.h
new file mode 100644
index 0000000..5254478
--- /dev/null
+++ b/include/linux/signaltrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009 Jiri Olsa <jolsa@redhat.com>
+ *
+ * This file is released under GPL version 2.
+ */
+
+#ifndef _LINUX_SIGNALTRACE_H
+#define _LINUX_SIGNALTRACE_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_SIGNAL_TRACER
+void trace_signal(struct task_struct *to, int sig);
+#else
+static inline void trace_signal(struct task_struct *to, int sig)
+{
+}
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SIGNALTRACE_H */
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 17ba82e..315b828 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -49,6 +49,7 @@
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/security.h>
+#include <linux/signaltrace.h>
struct linux_binprm;
/**
@@ -462,6 +463,19 @@ static inline int tracehook_get_signal(struct task_struct *task,
}
/**
+ * tracehook_send_signal
+ * @to: @current
+ * @sig: number of signal being sent
+ */
+static inline int tracehook_send_signal(struct task_struct *to, int sig)
+{
+#ifdef CONFIG_SIGNAL_TRACER
+ trace_signal(to, sig);
+#endif
+ return 0;
+}
+
+/**
* tracehook_notify_jctl - report about job control stop/continue
* @notify: nonzero if this is the last thread in the group to stop
* @why: %CLD_STOPPED or %CLD_CONTINUED
diff --git a/kernel/signal.c b/kernel/signal.c
index 64c5dee..8d3072b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -842,6 +842,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
return 0;
pending = group ? &t->signal->shared_pending : &t->pending;
+
+ tracehook_send_signal(t, sig);
+
/*
* Short-circuit ignored signals and support queuing
* exactly one non-rt signal, so that we can get more
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index d05a661..be47a1a 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -396,6 +396,17 @@ config HW_BRANCH_TRACER
This tracer records all branches on the system in a circular
buffer giving access to the last N branches for each cpu.
+config SIGNAL_TRACER
+ bool "Trace signals"
+ select TRACING
+ help
+ This tracer records sent signals in a circular buffer.
+ It is possible to narrow the trace using the "set_ftrace_pid"
+ pid filter file.
+
+ If unsure, say N.
+
+
config KMEMTRACE
bool "Trace SLAB allocations"
select GENERIC_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index ce3b1cd..a76c214 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -55,5 +55,6 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
obj-$(CONFIG_KSYM_TRACER) += trace_ksym.o
+obj-$(CONFIG_SIGNAL_TRACER) += trace_signal.o
libftrace-y := ftrace.o
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e747162..5c7873a 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -44,6 +44,7 @@ enum trace_type {
TRACE_POWER,
TRACE_BLK,
TRACE_KSYM,
+ TRACE_SIGNAL,
__TRACE_LAST_TYPE,
};
@@ -218,6 +219,7 @@ extern void __ftrace_bad_type(void);
IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
TRACE_KMEM_FREE); \
IF_ASSIGN(var, ent, struct ksym_trace_entry, TRACE_KSYM);\
+ IF_ASSIGN(var, ent, struct signal_trace_entry, TRACE_SIGNAL);\
__ftrace_bad_type(); \
} while (0)
@@ -254,6 +256,13 @@ struct ksym_trace_entry {
char cmd[TASK_COMM_LEN];
};
+/* Signal trace entry. */
+struct signal_trace_entry {
+ struct trace_entry ent;
+ int pid;
+ int sig;
+};
+
/**
* struct tracer - a specific tracer and its callbacks to interact with debugfs
* @name: the name chosen to select it on the available_tracers file
diff --git a/kernel/trace/trace_signal.c b/kernel/trace/trace_signal.c
new file mode 100644
index 0000000..4b386de
--- /dev/null
+++ b/kernel/trace/trace_signal.c
@@ -0,0 +1,132 @@
+/*
+ * signal tracer
+ *
+ * Copyright (C) 2009 Jiri Olsa <jolsa@redhat.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/ftrace.h>
+#include <linux/signaltrace.h>
+
+#include "trace.h"
+
+static char* signal_str[SIGRTMIN + 1] =
+{
+ "UNKNOWN", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP",
+ "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV",
+ "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD",
+ "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG",
+ "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO",
+ "SIGPWR", "SIGSYS"
+};
+
+static struct trace_array *ctx_trace;
+static int signal_trace_enabled = 0;
+
+void trace_signal(struct task_struct *to, int sig)
+{
+ struct ring_buffer_event *event;
+ struct signal_trace_entry *entry;
+ struct trace_array *tr = ctx_trace;
+
+ if (!ftrace_trace_task(current))
+ return;
+
+ if (!signal_trace_enabled)
+ return;
+
+ event = trace_buffer_lock_reserve(tr->buffer, TRACE_SIGNAL,
+ sizeof(*entry), 0, 0);
+ if (!event)
+ return;
+
+ tracing_record_cmdline(current);
+ tracing_record_cmdline(to);
+
+ entry = ring_buffer_event_data(event);
+ entry->pid = to->pid;
+ entry->sig = sig;
+
+ trace_buffer_unlock_commit(tr->buffer, event, 0, 0);
+}
+
+static void start_signal_trace(void)
+{
+ signal_trace_enabled = 1;
+}
+
+static void stop_signal_trace(void)
+{
+ signal_trace_enabled = 0;
+}
+
+static int signal_trace_init(struct trace_array *tr)
+{
+ ctx_trace = tr;
+ start_signal_trace();
+ return 0;
+}
+
+static void signal_trace_reset(struct trace_array *tr)
+{
+ stop_signal_trace();
+}
+
+static void trace_signal_print_header(struct seq_file *m)
+{
+ seq_printf(m, "# %12s %5s %16s-%-5s %16s-%-5s %14s-%-4s\n",
+ "TIMESTAMP", "CPU#", "FROM", "PID", "TO", "PID", "SIGNAL", "NUM");
+ seq_printf(m, "# %12s %5s %16s %-5s %16s %-5s %14s %-4s\n",
+ " | ", " | ", " |", "| ", " |", "| ", " |", "| ");
+}
+
+static enum print_line_t trace_signal_print_line(struct trace_iterator *iter)
+{
+ char to_comm[TASK_COMM_LEN], from_comm[TASK_COMM_LEN];
+ struct trace_seq *s = &iter->seq;
+ struct trace_entry *tr_entry = iter->ent;
+ struct signal_trace_entry *sig_entry = NULL;
+ int sig;
+ unsigned long long t = ns2usecs(iter->ts);
+ unsigned long usec_rem = do_div(t, USEC_PER_SEC);
+ unsigned long secs = (unsigned long)t;
+
+ trace_assign_type(sig_entry, iter->ent);
+ if (!sig_entry)
+ return TRACE_TYPE_UNHANDLED;
+
+ sig = sig_entry->sig < 0 ? 0 : sig_entry->sig;
+ if (sig > SIGRTMIN)
+ sig = 0;
+
+ trace_find_cmdline(tr_entry->pid, from_comm);
+ trace_find_cmdline(sig_entry->pid, to_comm);
+
+ trace_seq_printf(s, " %5lu.%06lu [%03d] %16s-%-5d %16s-%-5d %14s-%-4d\n",
+ secs, usec_rem, iter->cpu,
+ from_comm, tr_entry->pid,
+ to_comm, sig_entry->pid,
+ signal_str[sig], sig);
+
+ return TRACE_TYPE_HANDLED;
+}
+
+struct tracer signal_trace __read_mostly =
+{
+ .name = "signal",
+ .init = signal_trace_init,
+ .reset = signal_trace_reset,
+ .wait_pipe = poll_wait_pipe,
+ .print_header = trace_signal_print_header,
+ .print_line = trace_signal_print_line,
+};
+
+static __init int init_signal_trace(void)
+{
+ return register_tracer(&signal_trace);
+}
+
+device_initcall(init_signal_trace);
--
1.6.2.5
next prev parent reply other threads:[~2009-09-14 10:14 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-14 10:14 [RFC PATCH 0/2] tracing - signal tracer, support multiple pids in set_pid_ftrace jolsa
2009-09-14 10:14 ` jolsa [this message]
2009-09-14 10:14 ` [RFC PATCH 2/2] tracing - support multiple pids in set_pid_ftrace file jolsa
2009-09-14 12:20 ` [RFC PATCH 0/2] tracing - signal tracer, support multiple pids in set_pid_ftrace Steven Rostedt
2009-09-14 13:59 ` Daniel Walker
2009-09-14 14:05 ` Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1252923251-6735-2-git-send-email-jolsa@redhat.com \
--to=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.