Bug #17820
closed`Errno::EINVAL` from `Process.kill` with available signal on Windows
Added by AlexWayfer (Alexander Popov) over 3 years ago. Updated over 3 years ago.
Description
Hello.
I've installed Ruby on Windows via Chocolatey.
I receive Errno::EINVAL
from Process.kill
with almost every signal. Only 0
seems working. TERM
(15
), INT
(2
) — don't. Although they're in Signal.list
output:
Files
clipboard-202104222051-b64xq.png (63.9 KB) clipboard-202104222051-b64xq.png | AlexWayfer (Alexander Popov), 04/22/2021 05:51 PM | ||
clipboard-202104222318-tbufr.png (96.8 KB) clipboard-202104222318-tbufr.png | AlexWayfer (Alexander Popov), 04/22/2021 08:18 PM |
Updated by xtkoba (Tee KOBAYASHI) over 3 years ago
This seems to be a well-known restriction. Only KILL
(9
) works for Windows.
https://blog.simplificator.com/2016/01/18/how-to-kill-processes-on-windows-using-ruby/
Updated by AlexWayfer (Alexander Popov) over 3 years ago
xtkoba (Tee KOBAYASHI) wrote in #note-1:
This seems to be a well-known restriction. Only
KILL
(9
) works for Windows.https://blog.simplificator.com/2016/01/18/how-to-kill-processes-on-windows-using-ruby/
Yes, I found this article, and wanted to add the link to the issue description, but didn't find an ability to edit the description.
So, about this article and behavior:
- This behavior doesn't seem "well-known restriction", there is no explanation or details (why?) in the article or somewhere.
- Article highlights that even
KILL
signal works incorrect on Windows (but I guess it should be a separate issue). - Article suggests system command instead of Ruby method.
- There is should be consistency and understandable behavior in Ruby, even in Windows (as I know, Ruby should works on Windows). So, either
Signal.list
should return onlyKILL
and something else working, orProcess.kill
should works withTERM
and other signals. Anyway,Signal.list
output andProcess.kill
input should be synced.
Also I found this SO answer and there are only outputs too, without details and explanation, like "it should work, try and puzzle it out by yourself".
Updated by AlexWayfer (Alexander Popov) over 3 years ago
Also I found a very strange behavior with Signal.trap
, not sure is it related, but I'm still sure that all signals should be synchronized and consistent.
So… Signal.trap('KILL')
raises Invalid argument - SIGKILL (Errno::EINVAL)
. And other signals, which are incorrect for Process.kill
, don't raise errors:
Updated by xtkoba (Tee KOBAYASHI) over 3 years ago
The signals (except for EXIT
, that is a pseudo signal) listed in Signal.list
are valid to be sent to Process.pid
($$
).
I suppose it is not easy to make POSIX signals consistent with Windows.
Updated by AlexWayfer (Alexander Popov) over 3 years ago
xtkoba (Tee KOBAYASHI) wrote in #note-4:
The signals (except for
EXIT
, that is a pseudo signal) listed inSignal.list
are valid to be sent toProcess.pid
($$
).
Sorry, what? This method only returns process ID, what do you mean about "send signals to Process.pid
"?
xtkoba (Tee KOBAYASHI) wrote in #note-4:
I suppose it is not easy to make POSIX signals consistent with Windows.
Either the list of signals should be shortened and consistent among methods (Process.kill
, Signal.list
, Signal.trap
, etc.), or some of these methods should raise an exception, like Process.getpgid
: getpgid() function is unimplemented on this machine (NotImplementedError)
.
Updated by xtkoba (Tee KOBAYASHI) over 3 years ago
I mean for example the following script works even on Windows (MinGW32).
Process.kill :TERM, Process.pid
Updated by jeremyevans0 (Jeremy Evans) over 3 years ago
- Status changed from Open to Rejected
I tested every signal from Signal.list
on Windows 10, and all signals work in some fashion, assuming you send the signal to the current process. For Process.kill
:
- INT raises a standard Interrupt exception
- ILL/SEGV simulates a crash and generates a backtrace (does not run ensure blocks)
- ABRT/FPE/KILL exits immediately (does not run ensure blocks)
- TERM exits immediately (runs ensure blocks)
- EXIT doesn't work
However, EXIT works for Signal.trap
. This code prints 1
and then 2
:
Signal.trap('EXIT'){p 2}
begin
Process.kill('TERM', $$)
ensure
p 1
end
So all signals listed in Signal.list
are valid in some context. The documentation for Signal
itself states:
The list of available signal names and their interpretation is
system dependent.
So Ruby makes no guarantee that signal handling behavior will be consistent across systems.
Considering all this, I don't think the current behavior is a bug. If you think the behavior or documentation could be improved, please submit a pull request.
Updated by AlexWayfer (Alexander Popov) over 3 years ago
jeremyevans0 (Jeremy Evans) wrote in #note-7:
I tested every signal from
Signal.list
on Windows 10, and all signals work in some fashion, assuming you send the signal to the current process. ForProcess.kill
:
- INT raises a standard Interrupt exception
- ILL/SEGV simulates a crash and generates a backtrace (does not run ensure blocks)
- ABRT/FPE/KILL exits immediately (does not run ensure blocks)
- TERM exits immediately (runs ensure blocks)
- EXIT doesn't work
However, EXIT works for
Signal.trap
. This code prints1
and then2
:Signal.trap('EXIT'){p 2} begin Process.kill('TERM', $$) ensure p 1 end
So all signals listed in
Signal.list
are valid in some context. The documentation forSignal
itself states:The list of available signal names and their interpretation is system dependent.
So Ruby makes no guarantee that signal handling behavior will be consistent across systems.
Considering all this, I don't think the current behavior is a bug. If you think the behavior or documentation could be improved, please submit a pull request.
I'm glad that these things work for current process, and with such circumstances the current behavior can be left, but it's weird for me that the same doesn't work for other Ruby processes. I'm testing filewatcher-cli
with Windows, and the original author wants Filewatcher to be cross-independent, but there is restart-signal
option and I just can't test it properly on Windows. I've already changed the default value from TERM
to KILL
, already added a warning for any different value, but spawned test Ruby script should trap specific signal and save a file with it. And even if I want to trap the default value (KILL
) — I can't, I should trap EXIT
, but such signal doesn't stop process, and so on… terrible behavior for me. I understand that Windows is not primary platform for Ruby, but I wish improvements and consistency in this direction. I'm not an expert with process signals so I can't send a PR for this.