Signal-generation calls

The kernel provides two separate group of functions for signal generation: one set for generating signals on individual process and another for process thread groups.

  • Following is the list of important functions to generate signals on a process:
    send_sig(): Generates a specified signal on a process; this function is used widely by kernel services
  • end_sig_info(): Extends send_sig() with additional siginfo_t instances
  • force_sig(): Used to generate priority non-maskable signals which cannot be ignored or blocked
  • force_sig_info(): Extends force_sig() with additional siginfo_t instances.

All of these routines eventually invoke the core kernel function send_signal() which is programmed to generate a specified signal.

Following is the list of important functions to generate signals on a process group:

  • kill_pgrp(): Generates the specified signal on all thread groups in a process group
  • kill_pid(): Generates the specified signal to a thread group identified by a PID
  • kill_pid_info(): Extends kill_pid() with additional siginfo_t instances

All of these routines invoke a function group_send_sig_info() which eventually invokes send_signal() with appropriate parameters.
The send_signal() function is the core signal-generation function; it invokes the __send_signal() routine with appropriate arguments:

 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
int group)
{
int from_ancestor_ns = 0;

#ifdef CONFIG_PID_NS
from_ancestor_ns = si_fromuser(info) &&
!task_pid_nr_ns(current, task_active_pid_ns(t));
#endif

return __send_signal(sig, info, t, group, from_ancestor_ns);
}

Following are important steps executed by __send_signal():

  1. Check for the source of the signal from the info argument. If signal generation was initiated by the kernel for non-maskable SIGKILL or SIGSTOP, it immediately sets the appropriate bit of the sigpending bitmask, sets the TIF_SIGPENDING flag, and initiates the delivery process by waking up the target thread:
 /*
* fast-pathed signals for kernel-internal things like SIGSTOP
* or SIGKILL.
*/
if (info == SEND_SIG_FORCED)
goto out_set;
....
....
....
out_set:
signalfd_notify(t, sig);
sigaddset(&pending->signal, sig);
complete_signal(sig, t, group);

  1. Invoke the __sigqeueue_alloc() function, which checks if the number of pending signals for the receiver process is less than the resource limit. If true, it increments the pending signal counter and returns the address of the struct sigqueue instance:
 q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,
override_rlimit);
  1. Enqueue the sigqueue instance into the pending list and fill out the signal information into siginfo_t:
if (q) {
list_add_tail(&q->list, &pending->list);
switch ((unsigned long) info) {
case (unsigned long) SEND_SIG_NOINFO:
q->info.si_signo = sig;
q->info.si_errno = 0;
q->info.si_code = SI_USER;
q->info.si_pid = task_tgid_nr_ns(current,
task_active_pid_ns(t));
q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
break;
case (unsigned long) SEND_SIG_PRIV:
q->info.si_signo = sig;
q->info.si_errno = 0;
q->info.si_code = SI_KERNEL;
q->info.si_pid = 0;
q->info.si_uid = 0;
break;
default:
copy_siginfo(&q->info, info);
if (from_ancestor_ns)
q->info.si_pid = 0;
break;
}


  1. Set the appropriate signal bit in the pending signal's bitmask, and attempt signal delivery by invoking complete_signal(), which in turn sets the TIF_SIGPENDING flag:
 sigaddset(&pending->signal, sig);
complete_signal(sig, t, group);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.22.107