Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c303d3a authored by Oleg Nesterov's avatar Oleg Nesterov
Browse files

tracing: let trace_signal_generate() report more info, kill overflow_fail/lose_info



__send_signal()->trace_signal_generate() doesn't report enough info.
The users want to know was the signal actually delivered or not, and
they also need the shared/private info.

The patch moves trace_signal_generate() at the end of __send_signal()
and adds the 2 additional arguments.

This also allows us to kill trace_signal_overflow_fail/lose_info, we
can simply add the appropriate TRACE_SIGNAL_ "result" codes.

Reported-by: default avatarSeiji Aguchi <saguchi@redhat.com>
Reviewed-by: default avatarSeiji Aguchi <seiji.aguchi@hds.com>
Acked-by: default avatarSteven Rostedt <rostedt@goodmis.org>
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
parent 09946950
Loading
Loading
Loading
Loading
+22 −63
Original line number Original line Diff line number Diff line
@@ -23,11 +23,23 @@
		}						\
		}						\
	} while (0)
	} while (0)


#ifndef TRACE_HEADER_MULTI_READ
enum {
	TRACE_SIGNAL_DELIVERED,
	TRACE_SIGNAL_IGNORED,
	TRACE_SIGNAL_ALREADY_PENDING,
	TRACE_SIGNAL_OVERFLOW_FAIL,
	TRACE_SIGNAL_LOSE_INFO,
};
#endif

/**
/**
 * signal_generate - called when a signal is generated
 * signal_generate - called when a signal is generated
 * @sig: signal number
 * @sig: signal number
 * @info: pointer to struct siginfo
 * @info: pointer to struct siginfo
 * @task: pointer to struct task_struct
 * @task: pointer to struct task_struct
 * @group: shared or private
 * @result: TRACE_SIGNAL_*
 *
 *
 * Current process sends a 'sig' signal to 'task' process with
 * Current process sends a 'sig' signal to 'task' process with
 * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV,
 * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV,
@@ -37,9 +49,10 @@
 */
 */
TRACE_EVENT(signal_generate,
TRACE_EVENT(signal_generate,


	TP_PROTO(int sig, struct siginfo *info, struct task_struct *task),
	TP_PROTO(int sig, struct siginfo *info, struct task_struct *task,
			int group, int result),


	TP_ARGS(sig, info, task),
	TP_ARGS(sig, info, task, group, result),


	TP_STRUCT__entry(
	TP_STRUCT__entry(
		__field(	int,	sig			)
		__field(	int,	sig			)
@@ -47,6 +60,8 @@ TRACE_EVENT(signal_generate,
		__field(	int,	code			)
		__field(	int,	code			)
		__array(	char,	comm,	TASK_COMM_LEN	)
		__array(	char,	comm,	TASK_COMM_LEN	)
		__field(	pid_t,	pid			)
		__field(	pid_t,	pid			)
		__field(	int,	group			)
		__field(	int,	result			)
	),
	),


	TP_fast_assign(
	TP_fast_assign(
@@ -54,11 +69,14 @@ TRACE_EVENT(signal_generate,
		TP_STORE_SIGINFO(__entry, info);
		TP_STORE_SIGINFO(__entry, info);
		memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
		memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
		__entry->pid	= task->pid;
		__entry->pid	= task->pid;
		__entry->group	= group;
		__entry->result	= result;
	),
	),


	TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d",
	TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d grp=%d res=%d",
		  __entry->sig, __entry->errno, __entry->code,
		  __entry->sig, __entry->errno, __entry->code,
		  __entry->comm, __entry->pid)
		  __entry->comm, __entry->pid, __entry->group,
		  __entry->result)
);
);


/**
/**
@@ -101,65 +119,6 @@ TRACE_EVENT(signal_deliver,
		  __entry->sa_handler, __entry->sa_flags)
		  __entry->sa_handler, __entry->sa_flags)
);
);


DECLARE_EVENT_CLASS(signal_queue_overflow,

	TP_PROTO(int sig, int group, struct siginfo *info),

	TP_ARGS(sig, group, info),

	TP_STRUCT__entry(
		__field(	int,	sig	)
		__field(	int,	group	)
		__field(	int,	errno	)
		__field(	int,	code	)
	),

	TP_fast_assign(
		__entry->sig	= sig;
		__entry->group	= group;
		TP_STORE_SIGINFO(__entry, info);
	),

	TP_printk("sig=%d group=%d errno=%d code=%d",
		  __entry->sig, __entry->group, __entry->errno, __entry->code)
);

/**
 * signal_overflow_fail - called when signal queue is overflow
 * @sig: signal number
 * @group: signal to process group or not (bool)
 * @info: pointer to struct siginfo
 *
 * Kernel fails to generate 'sig' signal with 'info' siginfo, because
 * siginfo queue is overflow, and the signal is dropped.
 * 'group' is not 0 if the signal will be sent to a process group.
 * 'sig' is always one of RT signals.
 */
DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail,

	TP_PROTO(int sig, int group, struct siginfo *info),

	TP_ARGS(sig, group, info)
);

/**
 * signal_lose_info - called when siginfo is lost
 * @sig: signal number
 * @group: signal to process group or not (bool)
 * @info: pointer to struct siginfo
 *
 * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo
 * queue is overflow.
 * 'group' is not 0 if the signal will be sent to a process group.
 * 'sig' is always one of non-RT signals.
 */
DEFINE_EVENT(signal_queue_overflow, signal_lose_info,

	TP_PROTO(int sig, int group, struct siginfo *info),

	TP_ARGS(sig, group, info)
);

#endif /* _TRACE_SIGNAL_H */
#endif /* _TRACE_SIGNAL_H */


/* This part must be outside protection */
/* This part must be outside protection */
+14 −8
Original line number Original line Diff line number Diff line
@@ -1054,13 +1054,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
	struct sigpending *pending;
	struct sigpending *pending;
	struct sigqueue *q;
	struct sigqueue *q;
	int override_rlimit;
	int override_rlimit;

	int ret = 0, result;
	trace_signal_generate(sig, info, t);


	assert_spin_locked(&t->sighand->siglock);
	assert_spin_locked(&t->sighand->siglock);


	result = TRACE_SIGNAL_IGNORED;
	if (!prepare_signal(sig, t, from_ancestor_ns))
	if (!prepare_signal(sig, t, from_ancestor_ns))
		return 0;
		goto ret;


	pending = group ? &t->signal->shared_pending : &t->pending;
	pending = group ? &t->signal->shared_pending : &t->pending;
	/*
	/*
@@ -1068,8 +1068,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
	 * exactly one non-rt signal, so that we can get more
	 * exactly one non-rt signal, so that we can get more
	 * detailed information about the cause of the signal.
	 * detailed information about the cause of the signal.
	 */
	 */
	result = TRACE_SIGNAL_ALREADY_PENDING;
	if (legacy_queue(pending, sig))
	if (legacy_queue(pending, sig))
		return 0;
		goto ret;

	result = TRACE_SIGNAL_DELIVERED;
	/*
	/*
	 * fast-pathed signals for kernel-internal things like SIGSTOP
	 * fast-pathed signals for kernel-internal things like SIGSTOP
	 * or SIGKILL.
	 * or SIGKILL.
@@ -1127,14 +1130,15 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
			 * signal was rt and sent by user using something
			 * signal was rt and sent by user using something
			 * other than kill().
			 * other than kill().
			 */
			 */
			trace_signal_overflow_fail(sig, group, info);
			result = TRACE_SIGNAL_OVERFLOW_FAIL;
			return -EAGAIN;
			ret = -EAGAIN;
			goto ret;
		} else {
		} else {
			/*
			/*
			 * This is a silent loss of information.  We still
			 * This is a silent loss of information.  We still
			 * send the signal, but the *info bits are lost.
			 * send the signal, but the *info bits are lost.
			 */
			 */
			trace_signal_lose_info(sig, group, info);
			result = TRACE_SIGNAL_LOSE_INFO;
		}
		}
	}
	}


@@ -1142,7 +1146,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
	signalfd_notify(t, sig);
	signalfd_notify(t, sig);
	sigaddset(&pending->signal, sig);
	sigaddset(&pending->signal, sig);
	complete_signal(sig, t, group);
	complete_signal(sig, t, group);
	return 0;
ret:
	trace_signal_generate(sig, info, t, group, result);
	return ret;
}
}


static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
static int send_signal(int sig, struct siginfo *info, struct task_struct *t,