diff options
Diffstat (limited to 'include/ruby/internal/intern/signal.h')
| -rw-r--r-- | include/ruby/internal/intern/signal.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h new file mode 100644 index 0000000000..4773788651 --- /dev/null +++ b/include/ruby/internal/intern/signal.h @@ -0,0 +1,146 @@ +#ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SIGNAL_H +/** + * @file + * @author Ruby developers <ruby-core@ruby-lang.org> + * @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 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 */ |
