< prev index next >

src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c

Print this page
rev 12437 : 8131168: Refactor ProcessHandleImpl_*.c and add implememtation for AIX

@@ -26,172 +26,58 @@
 #include "jni.h"
 #include "jni_util.h"
 #include "java_lang_ProcessHandleImpl.h"
 #include "java_lang_ProcessHandleImpl_Info.h"
 
+#include "ProcessHandleImpl_unix.h"
+
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <sys/sysctl.h>
 
 /**
- * Implementations of ProcessHandleImpl functions for MAC OS X;
- * are NOT common to all Unix variants.
- */
-
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-
-/*
- * Common Unix function to lookup the uid and return the user name.
+ * Implementation of native ProcessHandleImpl functions for MAC OS X.
+ * See ProcessHandleImpl_unix.c for more details.
  */
-extern jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
 
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
+void os_initNative(JNIEnv *env, jclass clazz) {}
 
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
-    CHECK_NULL(ProcessHandleImpl_Info_commandID =
-            (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
-            (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
-            (*env)->GetFieldID(env, clazz, "totalTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
-            (*env)->GetFieldID(env, clazz, "startTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_userID =
-            (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
-}
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
-      clock_ticks_per_second = sysconf(_SC_CLK_TCK);
-}
-
-/*
- * Check if a process is alive.
- * Return the start time (ms since 1970) if it is available.
- * If the start time is not available return 0.
- * If the pid is invalid, return -1.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    isAlive0
- * Signature: (J)J
+/**
+ * Return the uid of a process or -1 on error
  */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
-    pid_t pid = (pid_t) jpid;
+uid_t os_getUID(pid_t pid) {
     struct kinfo_proc kp;
     size_t bufSize = sizeof kp;
 
     // Read the process info for the specific pid
     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 
-    if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-        return  (errno == EINVAL) ? -1 : 0;
-    } else {
-        return (bufSize == 0) ?  -1 :
-                                 (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
-                                        + kp.kp_proc.p_starttime.tv_usec / 1000);
-    }
-}
-
-/*
- * Returns the parent pid of the requested pid.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    parent0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
-                                         jobject obj,
-                                         jlong jpid,
-                                         jlong startTime) {
-    pid_t pid = (pid_t) jpid;
-    pid_t ppid = -1;
-
-    if (pid == getpid()) {
-        ppid = getppid();
-    } else {
-        const pid_t pid = (pid_t) jpid;
-        struct kinfo_proc kp;
-        size_t bufSize = sizeof kp;
-
-        // Read the process info for the specific pid
-        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
-        if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-            JNU_ThrowByNameWithLastError(env,
-                "java/lang/RuntimeException", "sysctl failed");
-            return -1;
-        }
-        // If the buffer is full and for the pid requested then check the start
+    if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) == 0) {
         if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
-            jlong start = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
-                                   + kp.kp_proc.p_starttime.tv_usec / 1000);
-            if (start == startTime || start == 0 || startTime == 0) {
-                ppid = kp.kp_eproc.e_ppid;
-            }
+            return kp.kp_eproc.e_ucred.cr_uid;
         }
     }
-    return (jlong) ppid;
+    return (uid_t)-1;
 }
 
 /*
  * Returns the children of the requested pid and optionally each parent.
  *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    getProcessPids0
- * Signature: (J[J[J)I
- *
  * Use sysctl to accumulate any process whose parent pid is zero or matches.
  * The resulting pids are stored into the array of longs.
  * The number of pids is returned if they all fit.
  * If the parentArray is non-null, store the parent pid.
  * If the array is too short, excess pids are not stored and
  * the desired length is returned.
  */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
-                                                 jclass clazz,
-                                                 jlong jpid,
-                                                 jlongArray jarray,
-                                                 jlongArray jparentArray,
-                                                 jlongArray jstimesArray) {
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                    jlongArray jparentArray, jlongArray jstimesArray) {
     jlong* pids = NULL;
     jlong* ppids = NULL;
     jlong* stimes = NULL;
     jsize parentArraySize = 0;
     jsize arraySize = 0;

@@ -301,121 +187,54 @@
     free(buffer);
     // If more pids than array had size for; count will be greater than array size
     return count;
 }
 
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
- */
-
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    info0
- * Signature: (J)I
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
-                                                 jobject jinfo,
-                                                 jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    getStatInfo(env, jinfo, pid);
-    getCmdlineInfo(env, jinfo, pid);
-}
-
 /**
- * Read /proc/<pid>/stat and fill in the fields of the Info object.
- * The executable name, plus the user, system, and start times are gathered.
+ * Use sysctl and return the ppid, total cputime and start time.
+ * Return: -1 is fail;  zero is unknown; >  0 is parent pid
  */
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) {
-    jlong totalTime;                    // nanoseconds
-    unsigned long long startTime;       // milliseconds
+pid_t os_getParentPid(JNIEnv *env, pid_t jpid, jlong *totalTime, jlong *startTime) {
 
     const pid_t pid = (pid_t) jpid;
     struct kinfo_proc kp;
     size_t bufSize = sizeof kp;
 
     // Read the process info for the specific pid
     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 
     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-        if (errno == EINVAL) {
-            return;
-        } else {
             JNU_ThrowByNameWithLastError(env,
                 "java/lang/RuntimeException", "sysctl failed");
+        return -1;
         }
-        return;
-    }
-
-    // Convert the UID to the username
-    jstring name = NULL;
-    CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid)));
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
-    JNU_CHECK_EXCEPTION(env);
 
-    startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
+    if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
+      *startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
                 kp.kp_proc.p_starttime.tv_usec / 1000;
-
-    (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
-    JNU_CHECK_EXCEPTION(env);
+    }
 
     // Get cputime if for current process
     if (pid == getpid()) {
         struct rusage usage;
-        if (getrusage(RUSAGE_SELF, &usage) != 0) {
-            return;
-        }
+        if (getrusage(RUSAGE_SELF, &usage) == 0) {
         jlong microsecs =
             usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
             usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
-        totalTime = microsecs * 1000;
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
-        JNU_CHECK_EXCEPTION(env);
-    }
-}
-
-/**
- * Construct the argument array by parsing the arguments from the sequence of arguments.
- */
-static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs,
-                        const char *cp, const char *argsEnd) {
-    jstring str = NULL;
-    jobject argsArray;
-    int i;
-
-    if (nargs < 1) {
-        return 0;
+          *totalTime = microsecs * 1000;
     }
-    // Create a String array for nargs-1 elements
-    CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env,
-            nargs - 1, JNU_ClassString(env), NULL)), -1);
-
-    for (i = 0; i < nargs - 1; i++) {
-        // skip to the next argument; omits arg[0]
-        cp += strnlen(cp, (argsEnd - cp)) + 1;
-
-        if (cp > argsEnd || *cp == '\0') {
-            return -2;  // Off the end pointer or an empty argument is an error
         }
 
-        CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
+    return (bufSize > 0 && kp.kp_proc.p_pid == pid) ? kp.kp_eproc.e_ppid : -1;
 
-        (*env)->SetObjectArrayElement(env, argsArray, i, str);
-        JNU_CHECK_EXCEPTION_RETURN(env, -3);
-    }
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
-    JNU_CHECK_EXCEPTION_RETURN(env, -4);
-    return 0;
 }
 
 /**
  * Retrieve the command and arguments for the process and store them
  * into the Info object.
  */
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+void os_getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
     int mib[3], maxargs, nargs, i;
     size_t size;
     char *args, *cp, *sp, *np;
 
     // Get the maximum size of the arguments

@@ -435,11 +254,11 @@
         return;
     }
 
     do {            // a block to break out of on error
         char *argsEnd;
-        jstring str = NULL;
+        jstring cmdexe = NULL;
 
         mib[0] = CTL_KERN;
         mib[1] = KERN_PROCARGS2;
         mib[2] = pid;
         size = (size_t) maxargs;

@@ -454,26 +273,22 @@
 
         cp = &args[sizeof(nargs)];      // Strings start after nargs
         argsEnd = &args[size];
 
         // Store the command executable path
-        if ((str = JNU_NewStringPlatform(env, cp)) == NULL) {
-            break;
-        }
-        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
-        if ((*env)->ExceptionCheck(env)) {
+        if ((cmdexe = JNU_NewStringPlatform(env, cp)) == NULL) {
             break;
         }
 
         // Skip trailing nulls after the executable path
         for (cp = cp + strnlen(cp, argsEnd - cp); cp < argsEnd; cp++) {
             if (*cp != '\0') {
                 break;
             }
         }
 
-        fillArgArray(env, jinfo, nargs, cp, argsEnd);
+        unix_fillArgArray(env, jinfo, nargs, cp, argsEnd, cmdexe);
     } while (0);
     // Free the arg buffer
     free(args);
 }
 
< prev index next >