Skip to content
This repository

Windows Process.kill 'KILL' #320

Closed
wants to merge 8 commits into from

2 participants

Roger Pack Charles Oliver Nutter
Roger Pack

Implements Process.kill 'KILL', pid
for windows. Kind of based off this other pull request being merged first:
#319
see http://jira.codehaus.org/browse/JRUBY-4317

Roger Pack

this may have been ill founded

Charles Oliver Nutter headius referenced this pull request from a commit September 28, 2012
Charles Oliver Nutter From pull request #320
Implements Process.kill 'KILL', pid

Squashed commit of the following:

commit 3312da9
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 03:04:40 2012 -0600

    clarify error message

commit 7c2deab
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 00:52:33 2012 -0600

    use finally clause for cleanup

commit 2a0d502
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 00:45:40 2012 -0600

    better liveness check

commit fcf0f1d
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:31:14 2012 -0600

    working kill

commit 41d7c77
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:27:29 2012 -0600

    closer

commit 0339c40
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:26:30 2012 -0600

    almost flesh out Process.kill 'KILL' for windows

commit 98f1af9
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 17:44:12 2012 -0600

     implement Signal.kill 0 for windows

commit 6e2df4a
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 16:54:04 2012 -0600

    throw not implemented for unimplemented signals in windows
eeefa64
Charles Oliver Nutter headius closed this September 28, 2012
प्रथमेश prathamesh-sonpatki referenced this pull request from a commit in prathamesh-sonpatki/jruby September 28, 2012
Charles Oliver Nutter From pull request #320
Implements Process.kill 'KILL', pid

Squashed commit of the following:

commit 3312da9
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 03:04:40 2012 -0600

    clarify error message

commit 7c2deab
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 00:52:33 2012 -0600

    use finally clause for cleanup

commit 2a0d502
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Fri Sep 28 00:45:40 2012 -0600

    better liveness check

commit fcf0f1d
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:31:14 2012 -0600

    working kill

commit 41d7c77
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:27:29 2012 -0600

    closer

commit 0339c40
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 18:26:30 2012 -0600

    almost flesh out Process.kill 'KILL' for windows

commit 98f1af9
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 17:44:12 2012 -0600

     implement Signal.kill 0 for windows

commit 6e2df4a
Author: rogerdpack <rogerpack2005@gmail.com>
Date:   Wed Sep 26 16:54:04 2012 -0600

    throw not implemented for unimplemented signals in windows
8fb82a2
Luca Simone lukefx referenced this pull request from a commit December 04, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 86 additions and 17 deletions. Show diff stats Hide diff stats

  1. 103  src/org/jruby/RubyProcess.java
103  src/org/jruby/RubyProcess.java
@@ -29,6 +29,7 @@
29 29
  ***** END LICENSE BLOCK *****/
30 30
 package org.jruby;
31 31
 
  32
+import jnr.ffi.*;
32 33
 import jnr.constants.platform.Signal;
33 34
 import jnr.constants.platform.Sysconf;
34 35
 import jnr.posix.Times;
@@ -874,7 +875,15 @@ private static int parseSignalString(Ruby runtime, String value) {
874 875
             throw runtime.newArgumentError("unsupported name `SIG" + signalName + "'");
875 876
         }
876 877
     }
877  
-
  878
+	
  879
+    public static interface Kernel32  {
  880
+        jnr.ffi.Pointer OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);
  881
+		int CloseHandle(jnr.ffi.Pointer handle);
  882
+		int GetLastError();
  883
+		int GetExitCodeProcess(jnr.ffi.Pointer hProcess, jnr.ffi.Pointer pointerToExitCodeDword);
  884
+		int TerminateProcess(jnr.ffi.Pointer hProcess, int uExitCode);
  885
+    }
  886
+	
878 887
     @Deprecated
879 888
     public static IRubyObject kill(IRubyObject recv, IRubyObject[] args) {
880 889
         return kill(recv.getRuntime(), args);
@@ -888,12 +897,6 @@ public static IRubyObject kill(Ruby runtime, IRubyObject[] args) {
888 897
             throw runtime.newArgumentError("wrong number of arguments -- kill(sig, pid...)");
889 898
         }
890 899
 
891  
-        // Windows does not support these functions, so we won't even try
892  
-        // This also matches Ruby behavior for JRUBY-2353.
893  
-        if (Platform.IS_WINDOWS) {
894  
-            return runtime.getNil();
895  
-        }
896  
-        
897 900
         int signal;
898 901
         if (args[0] instanceof RubyFixnum) {
899 902
             signal = (int) ((RubyFixnum) args[0]).getLongValue();
@@ -907,18 +910,84 @@ public static IRubyObject kill(Ruby runtime, IRubyObject[] args) {
907 910
 
908 911
         boolean processGroupKill = signal < 0;
909 912
         
910  
-        if (processGroupKill) signal = -signal;
911  
-        
912  
-        POSIX posix = runtime.getPosix();
913  
-        for (int i = 1; i < args.length; i++) {
914  
-            int pid = RubyNumeric.num2int(args[i]);
915  
-
916  
-            // FIXME: It may be possible to killpg on systems which support it.  POSIX library
917  
-            // needs to tell whether a particular method works or not
918  
-            if (pid == 0) pid = runtime.getPosix().getpid();
919  
-            checkErrno(runtime, posix.kill(processGroupKill ? -pid : pid, signal));
  913
+        if (processGroupKill) {
  914
+		    if (Platform.IS_WINDOWS) {
  915
+                throw  runtime.newErrnoEINVALError("group signals not implemented in windows");
  916
+            }
  917
+		    signal = -signal;
920 918
         }
921 919
         
  920
+		if (Platform.IS_WINDOWS) {
  921
+			int PROCESS_QUERY_INFORMATION  = 0x0400;
  922
+			int ERROR_INVALID_PARAMETER = 0x57;
  923
+			int PROCESS_TERMINATE  = 0x0001;
  924
+			int STILL_ACTIVE = 259;
  925
+			Kernel32 libc = Library.loadLibrary("kernel32", Kernel32.class);
  926
+ 		    jnr.ffi.Pointer status = Memory.allocate(Library.getRuntime(libc), 4);
  927
+		    for (int i = 1; i < args.length; i++) {
  928
+			    int pid = RubyNumeric.num2int(args[i]);
  929
+		        if (signal == 0) {	                
  930
+				    jnr.ffi.Pointer ptr = libc.OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
  931
+				    if(ptr != null && ptr.address() != -1) {
  932
+					   try {
  933
+					       if(libc.GetExitCodeProcess(ptr, status) == 0) {
  934
+					          throw runtime.newErrnoEPERMError("unable to call GetExitCodeProcess " + pid);
  935
+					       } else {
  936
+					           if(status.getInt(0) != STILL_ACTIVE) {
  937
+							       throw runtime.newErrnoEPERMError("Process exists but is not alive anymore " + pid);
  938
+                               }
  939
+					       }
  940
+					   } finally {
  941
+					     libc.CloseHandle(ptr);
  942
+					   }
  943
+					   
  944
+					} else {
  945
+					    if (libc.GetLastError() == ERROR_INVALID_PARAMETER) {
  946
+					        throw runtime.newErrnoESRCHError();
  947
+					    } else {
  948
+					        throw runtime.newErrnoEPERMError("Process does not exist " + pid);
  949
+					    }
  950
+					}
  951
+			    } else if (signal == 9) { //SIGKILL
  952
+				    jnr.ffi.Pointer ptr = libc.OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, 0, pid);			      
  953
+                    if(ptr != null && ptr.address() != -1) {
  954
+					    try {
  955
+					        if(libc.GetExitCodeProcess(ptr, status) == 0) {
  956
+					            throw runtime.newErrnoEPERMError("unable to call GetExitCodeProcess " + pid); // todo better error messages
  957
+					        } else {
  958
+					            if (status.getInt(0) == STILL_ACTIVE) {
  959
+						            if (libc.TerminateProcess(ptr, 0) == 0) {
  960
+						               throw runtime.newErrnoEPERMError("unable to call TerminateProcess " + pid);
  961
+						             }
  962
+                                     // success									 
  963
+						        }
  964
+					        }
  965
+						} finally {						   
  966
+					       libc.CloseHandle(ptr);
  967
+					    }
  968
+					} else {
  969
+					    if (libc.GetLastError() == ERROR_INVALID_PARAMETER) {
  970
+					        throw runtime.newErrnoESRCHError();
  971
+					    } else {
  972
+					        throw runtime.newErrnoEPERMError("Process does not exist " + pid);
  973
+					    }
  974
+					}					
  975
+				} else {
  976
+		            throw runtime.newNotImplementedError("this signal not yet implemented in windows");
  977
+		        }
  978
+            }			
  979
+		} else {		
  980
+			POSIX posix = runtime.getPosix();
  981
+			for (int i = 1; i < args.length; i++) {
  982
+				int pid = RubyNumeric.num2int(args[i]);
  983
+
  984
+				// FIXME: It may be possible to killpg on systems which support it.  POSIX library
  985
+				// needs to tell whether a particular method works or not
  986
+				if (pid == 0) pid = runtime.getPosix().getpid();
  987
+				checkErrno(runtime, posix.kill(processGroupKill ? -pid : pid, signal));
  988
+			}
  989
+		}
  990
+        
922 991
         return runtime.newFixnum(args.length - 1);
923 992
 
924 993
     }
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.