Windows signal #319

Closed
wants to merge 2 commits into
from
View
64 src/org/jruby/RubyProcess.java
@@ -29,6 +29,7 @@
***** END LICENSE BLOCK *****/
package org.jruby;
+import jnr.ffi.*;
import jnr.constants.platform.Signal;
import jnr.constants.platform.Sysconf;
import jnr.posix.Times;
@@ -874,7 +875,13 @@ private static int parseSignalString(Ruby runtime, String value) {
throw runtime.newArgumentError("unsupported name `SIG" + signalName + "'");
}
}
-
+
+ public static interface Kernel32 {
+ jnr.ffi.Pointer OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);
+ int CloseHandle(jnr.ffi.Pointer handle);
+ int GetLastError();
+ }
+
@Deprecated
public static IRubyObject kill(IRubyObject recv, IRubyObject[] args) {
return kill(recv.getRuntime(), args);
@@ -888,12 +895,6 @@ public static IRubyObject kill(Ruby runtime, IRubyObject[] args) {
throw runtime.newArgumentError("wrong number of arguments -- kill(sig, pid...)");
}
- // Windows does not support these functions, so we won't even try
- // This also matches Ruby behavior for JRUBY-2353.
- if (Platform.IS_WINDOWS) {
- return runtime.getNil();
- }
-
int signal;
if (args[0] instanceof RubyFixnum) {
signal = (int) ((RubyFixnum) args[0]).getLongValue();
@@ -907,18 +908,47 @@ public static IRubyObject kill(Ruby runtime, IRubyObject[] args) {
boolean processGroupKill = signal < 0;
- if (processGroupKill) signal = -signal;
-
- POSIX posix = runtime.getPosix();
- for (int i = 1; i < args.length; i++) {
- int pid = RubyNumeric.num2int(args[i]);
-
- // FIXME: It may be possible to killpg on systems which support it. POSIX library
- // needs to tell whether a particular method works or not
- if (pid == 0) pid = runtime.getPosix().getpid();
- checkErrno(runtime, posix.kill(processGroupKill ? -pid : pid, signal));
+ if (processGroupKill) {
+ if (Platform.IS_WINDOWS) {
+ throw runtime.newErrnoEINVALError("group signals not implemented in windows");
+ }
+ signal = -signal;
}
+ if (Platform.IS_WINDOWS) {
+ if (signal == 0) {
+ Kernel32 libc = Library.loadLibrary("kernel32", Kernel32.class);
+ int PROCESS_QUERY_INFORMATION = 0x0400;
+ int ERROR_INVALID_PARAMETER = 0x57;
+ for (int i = 1; i < args.length; i++) {
+ int pid = RubyNumeric.num2int(args[i]);
+ jnr.ffi.Pointer ptr = libc.OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
+ if(ptr != null && ptr.address() != -1) {
+ libc.CloseHandle(ptr); // success
+ } else {
+ if (libc.GetLastError() == ERROR_INVALID_PARAMETER) {
+ throw runtime.newErrnoESRCHError();
+ } else {
+ throw runtime.newErrnoEPERMError("Process does not exist " + pid);
+ }
+ }
+ }
+
+ } else {
+ throw runtime.newNotImplementedError("this signal not yet implemented in windows");
+ }
+ } else {
+ POSIX posix = runtime.getPosix();
+ for (int i = 1; i < args.length; i++) {
+ int pid = RubyNumeric.num2int(args[i]);
+
+ // FIXME: It may be possible to killpg on systems which support it. POSIX library
+ // needs to tell whether a particular method works or not
+ if (pid == 0) pid = runtime.getPosix().getpid();
+ checkErrno(runtime, posix.kill(processGroupKill ? -pid : pid, signal));
+ }
+ }
+
return runtime.newFixnum(args.length - 1);
}