diff --git a/common/source/java/ch/systemsx/cisd/common/os/Unix.java b/common/source/java/ch/systemsx/cisd/common/os/Unix.java index 22b850bb84ef74ab99d8dee31f65e2a8b8743615..e03bd6f7431ace7c6d7314509037b6e3913aeaf3 100644 --- a/common/source/java/ch/systemsx/cisd/common/os/Unix.java +++ b/common/source/java/ch/systemsx/cisd/common/os/Unix.java @@ -16,8 +16,11 @@ package ch.systemsx.cisd.common.os; +import java.io.File; import java.io.IOException; +import ch.rinn.restrictions.Private; +import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.common.exceptions.WrappedIOException; import ch.systemsx.cisd.common.filesystem.FileUtilities; @@ -33,8 +36,15 @@ import ch.systemsx.cisd.common.filesystem.FileUtilities; public class Unix { + private enum ProcessDetection + { + PROCFS, PS, NONE + } + private final static boolean operational; + private final static ProcessDetection processDetection; + static { operational = FileUtilities.loadNativeLibraryFromResource("unix"); @@ -42,6 +52,16 @@ public class Unix { init(); } + if (isProcessRunningProcFS(1)) + { + processDetection = ProcessDetection.PROCFS; + } else if (isProcessRunningPS(1)) + { + processDetection = ProcessDetection.PS; + } else + { + processDetection = ProcessDetection.NONE; + } } /** @@ -355,6 +375,32 @@ public class Unix private static native String strerror(); + @Private + static boolean isProcessRunningProcFS(int pid) + { + return new File("/proc/" + pid).isDirectory(); + } + + @Private + static boolean isProcessRunningPS(int pid) + { + try + { + return Runtime.getRuntime().exec(new String[] + { "ps", "-p", Integer.toString(pid) }).waitFor() == 0; + } catch (IOException ex) + { + return false; + } catch (InterruptedException ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } + } + + // + // Public + // + /** * Returns <code>true</code>, if the native library has been loaded successfully and the link * utilities are operational, <code>false</code> otherwise. @@ -364,6 +410,14 @@ public class Unix return operational; } + /** + * Returns <code>true</code>, if process detection is available on this system. + */ + public static boolean canDetectProcesses() + { + return processDetection != ProcessDetection.NONE; + } + // // Process functions // @@ -376,6 +430,24 @@ public class Unix return getpid(); } + /** + * Returns <code>true</code>, if the process with <var>pid</var> is currently running and + * <code>false</code>, if it is not running or if process detection is not available ( + * {@link #canDetectProcesses()} <code>== false</code>). + */ + public static boolean isProcessRunning(int pid) + { + switch (processDetection) + { + case PROCFS: + return isProcessRunningProcFS(pid); + case PS: + return isProcessRunningPS(pid); + default: + return false; + } + } + /** * Returns the uid of the user that started this process. */ diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/os/UnixTests.java b/common/sourceTest/java/ch/systemsx/cisd/common/os/UnixTests.java index eedc47575c4de6600eb9baee4248398f5d9b5b13..154b2287ad92b2aebfb0c5659cb8f39241aed905 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/os/UnixTests.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/os/UnixTests.java @@ -23,6 +23,7 @@ import java.lang.reflect.Method; import org.testng.annotations.Test; +import ch.rinn.restrictions.Friend; import ch.systemsx.cisd.common.filesystem.AbstractFileSystemTestCase; import ch.systemsx.cisd.common.filesystem.FileUtilities; import ch.systemsx.cisd.common.os.FileLinkType; @@ -38,6 +39,7 @@ import static org.testng.AssertJUnit.*; * * @author Bernd Rinn */ +@Friend(toClasses = Unix.class) public class UnixTests extends AbstractFileSystemTestCase { @@ -262,6 +264,15 @@ public class UnixTests extends AbstractFileSystemTestCase assertTrue(user.getShell().startsWith("/")); } + @Test(groups = + { "requires_unix" }) + public void testDetectProcess() + { + assertTrue(Unix.canDetectProcesses()); + assertTrue(Unix.isProcessRunningProcFS(1)); + assertTrue(Unix.isProcessRunningPS(1)); + } + public static void main(String[] args) throws Throwable { final UnixTests test = new UnixTests();