1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_INTERN_SIGNAL_H
/**
* @file
* @author Ruby developers <[email protected]>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Signal handling APIs.
*/
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* signal.c */
RBIMPL_ATTR_NONNULL(())
/**
* Sends a signal ("kills") to processes.
*
* The first argument is the signal, either in:
*
* - Numerical representation (e.g. `9`), or
* - Textual representation of canonical (e.g. `:SIGKILL`) name or
* abbreviated (e.g. `:KILL`) name, either in ::rb_cSymbol or ::rb_cString.
*
* All the remaining arguments are numerical representations of process IDs.
* This function iterates over them to send the specified signal.
*
* You can specify both negative PIDs and negative signo to this function:
*
* ```
* sig \ pid | >= 1 | == 0 | == -1 | <= -2
* ===========+======+======+=======+=======
* > 0 | #1 | #2 | #3 | #4
* == 0 | #5 | #6 | #7 | #8
* < 0 | #9 | #10 | #11
* ```
*
* - Case #1: When signo and PID are both positive, this function sends the
* specified signal to the specified process (intuitive).
*
* - Case #2: When signo is positive and PID is zero, this function sends
* that signal to the current process group.
*
* - Case #3: When signo is positive and PID is -1, this function sends that
* signal to everything that the current process is allowed to kill.
*
* - Case #4: When signo is positive and PID is negative (but not -1), this
* function sends that signal to every processes in a process group, whose
* process group ID is the absolute value of the passed PID.
*
* - Case #5: When signo is zero and PID is positive, this function just
* checks for the existence of the specified process and doesn't send
* anything to anyone. In case the process is absent `Errno::ESRCH` is
* raised.
*
* - Case #6: When signo and PID are both zero, this function checks for the
* existence of the current process group. And it must do. This function
* is effectively a no-op then.
*
* - Case #7: When signo is zero and PID is -1, this function checks if there
* is any other process that the current process can kill. At least init
* (PID 1) must exist, so this must not fail.
*
* - Case #8: When signo is zero and PID is negative (but not -1), this
* function checks if there is a process group whose process group ID is
* the absolute value of the passed PID. In case the process group is
* absent `Errno::ESRCH` is raised.
*
* - Case #9: When signo is negative and PID is positive, this function sends
* the absolute value of the passed signo to the process group specified as
* the PID.
*
* - Case #10: When signo is negative and PID is zero, it is highly expected
* that this function sends the absolute value of the passed signo to the
* current process group. Strictly speaking, IEEE Std 1003.1-2017
* specifies that this (`killpg(3posix)` with an argument of zero) is an
* undefined behaviour. But no operating system is known so far that does
* things differently.
*
* - Case #11: When signo and PID are both negative, the behaviour of this
* function depends on how `killpg(3)` works. On Linux, it seems such
* attempt is strictly prohibited and `Errno::EINVAL` is raised. But on
* macOS, it seems it tries to to send the signal actually to the process
* group.
*
* @note Above description is in fact different from how `kill(2)` works.
* We interpret the passed arguments before passing them through to
* system calls.
* @param[in] argc Number of objects in `argv`.
* @param[in] argv Signal, followed by target PIDs.
* @exception rb_eArgError Unknown signal name.
* @exception rb_eSystemCallError Various errors sending signal to processes.
* @return Something numeric. The meaning of this return value is unclear.
* It seems in case of #1 above, this could be the body count. But
* other cases remain mysterious.
*/
VALUE rb_f_kill(int argc, const VALUE *argv);
RBIMPL_ATTR_PURE()
/**
* Queries the name of the signal. It returns for instance `"KILL"` for
* SIGKILL.
*
* @param[in] signo Signal number to query.
* @retval 0 No such signal.
* @retval otherwise A pointer to a static C string that is the name of
* the signal.
* @warning Don't free the return value.
*/
const char *ruby_signal_name(int signo);
/**
* Pretends as if there was no custom signal handler. This function sets the
* signal action to SIG_DFL, then kills itself.
*
* @param[in] sig The signal.
* @post Previous signal handler is lost.
* @post Passed signal is sent to the current process.
*
* @internal
*
* @shyouhei doesn't understand the needs of this function being visible from
* extension libraries.
*/
void ruby_default_signal(int sig);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_INTERN_SIGNAL_H */
|