< prev index next >

src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c

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


  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "jni_util.h"
  28 #include "java_lang_ProcessHandleImpl.h"
  29 #include "java_lang_ProcessHandleImpl_Info.h"
  30 


  31 
  32 #include <stdio.h>
  33 #include <ctype.h>
  34 #include <dirent.h>
  35 #include <errno.h>
  36 #include <fcntl.h>
  37 #include <procfs.h>
  38 #include <signal.h>
  39 #include <stdlib.h>
  40 #include <sys/stat.h>
  41 #include <sys/types.h>
  42 #include <unistd.h>
  43 #include <limits.h>
  44 
  45 /**
  46  * Implementations of ProcessHandleImpl functions that are
  47  * NOT common to all Unix variants:
  48  * - getProcessPids0(pid, pidArray)
  49  *
  50  * Implementations of ProcessHandleImpl_Info
  51  * - totalTime, startTime
  52  * - Command
  53  * - Arguments
  54  */
  55 
  56 /*
  57  * Signatures for internal OS specific functions.
  58  */
  59 static pid_t getStatInfo(JNIEnv *env, pid_t pid,
  60                                      jlong *totalTime, jlong* startTime,
  61                                      uid_t *uid);
  62 static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
  63 
  64 extern jstring uidToUser(JNIEnv* env, uid_t uid);
  65 
  66 /* Field id for jString 'command' in java.lang.ProcessHandle.Info */
  67 static jfieldID ProcessHandleImpl_Info_commandID;
  68 
  69 /* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
  70 static jfieldID ProcessHandleImpl_Info_argumentsID;
  71 
  72 /* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
  73 static jfieldID ProcessHandleImpl_Info_totalTimeID;
  74 
  75 /* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
  76 static jfieldID ProcessHandleImpl_Info_startTimeID;
  77 
  78 /* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
  79 static jfieldID ProcessHandleImpl_Info_userID;
  80 
  81 /* static value for clock ticks per second. */
  82 static long clock_ticks_per_second;
  83 
  84 /**************************************************************
  85  * Static method to initialize field IDs and the ticks per second rate.
  86  *
  87  * Class:     java_lang_ProcessHandleImpl_Info
  88  * Method:    initIDs
  89  * Signature: ()V
  90  */
  91 JNIEXPORT void JNICALL
  92 Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
  93     CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
  94         clazz, "command", "Ljava/lang/String;"));
  95     CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
  96         clazz, "arguments", "[Ljava/lang/String;"));
  97     CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
  98         clazz, "totalTime", "J"));
  99     CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env,
 100         clazz, "startTime", "J"));
 101     CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env,
 102         clazz, "user", "Ljava/lang/String;"));
 103 }
 104 
 105 /**************************************************************
 106  * Static method to initialize the ticks per second rate.
 107  *
 108  * Class:     java_lang_ProcessHandleImpl
 109  * Method:    initNative
 110  * Signature: ()V
 111  */
 112 JNIEXPORT void JNICALL
 113 Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
 114     clock_ticks_per_second = sysconf(_SC_CLK_TCK);
 115 }
 116 
 117 /*
 118  * Check if a process is alive.
 119  * Return the start time (ms since 1970) if it is available.
 120  * If the start time is not available return 0.
 121  * If the pid is invalid, return -1.
 122  *
 123  * Class:     java_lang_ProcessHandleImpl
 124  * Method:    isAlive0
 125  * Signature: (J)J
 126  */
 127 JNIEXPORT jlong JNICALL
 128 Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
 129     pid_t pid = (pid_t) jpid;
 130     jlong startTime = 0L;
 131     jlong totalTime = 0L;
 132     uid_t uid = -1;
 133     pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
 134     return (ppid < 0) ? -1 : startTime;
 135 }
 136 
 137 /*
 138  * Returns the parent pid of the requested pid.
 139  *
 140  * Class:     java_lang_ProcessHandleImpl
 141  * Method:    parent0
 142  * Signature: (J)J
 143  */
 144 JNIEXPORT jlong JNICALL
 145 Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
 146                                          jobject obj,
 147                                          jlong jpid,
 148                                          jlong startTime) {
 149     pid_t pid = (pid_t) jpid;
 150     pid_t ppid = -1;
 151 
 152     if (pid == getpid()) {
 153         ppid = getppid();
 154     } else {
 155         jlong start = 0L;
 156         jlong total = 0L;
 157         uid_t uid = -1;
 158 
 159         pid_t ppid = getStatInfo(env, pid, &total, &start, &uid);
 160         if (start != startTime
 161             && start != 0
 162             && startTime != 0) {
 163             ppid = -1;
 164         }
 165     }
 166     return (jlong) ppid;
 167 }
 168 
 169 /*
 170  * Returns the children of the requested pid and optionally each parent.
 171  *
 172  * Class:     java_lang_ProcessHandleImpl
 173  * Method:    getChildPids
 174  * Signature: (J[J)I
 175  *
 176  * Reads /proc and accumulates any process who parent pid matches.
 177  * The resulting pids are stored into the array of longs.
 178  * The number of pids is returned if they all fit.
 179  * If the array is too short, the desired length is returned.
 180  */
 181 JNIEXPORT jint JNICALL
 182 Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
 183                                                  jclass clazz,
 184                                                  jlong jpid,
 185                                                  jlongArray jarray,
 186                                                  jlongArray jparentArray,
 187                                                  jlongArray jstimesArray) {
 188     DIR* dir;
 189     struct dirent* ptr;
 190     pid_t pid = (pid_t) jpid;
 191     jlong* pids = NULL;
 192     jlong* ppids = NULL;
 193     jlong* stimes = NULL;
 194     jsize parentArraySize = 0;
 195     jsize arraySize = 0;
 196     jsize stimesSize = 0;
 197     jsize count = 0;
 198     char procname[32];
 199 
 200     arraySize = (*env)->GetArrayLength(env, jarray);
 201     JNU_CHECK_EXCEPTION_RETURN(env, 0);
 202     if (jparentArray != NULL) {
 203         parentArraySize = (*env)->GetArrayLength(env, jparentArray);
 204         JNU_CHECK_EXCEPTION_RETURN(env, 0);
 205 
 206         if (arraySize != parentArraySize) {
 207             JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
 208             return 0;
 209         }
 210     }
 211     if (jstimesArray != NULL) {
 212         stimesSize = (*env)->GetArrayLength(env, jstimesArray);
 213         JNU_CHECK_EXCEPTION_RETURN(env, -1);
 214 
 215         if (arraySize != stimesSize) {
 216             JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
 217             return 0;
 218         }
 219     }
 220 
 221     /*
 222      * To locate the children we scan /proc looking for files that have a
 223      * positive integer as a filename.
 224      */
 225     if ((dir = opendir("/proc")) == NULL) {
 226         JNU_ThrowByNameWithLastError(env,
 227             "java/lang/Runtime", "Unable to open /proc");
 228         return 0;
 229     }
 230 
 231     do { // Block to break out of on Exception
 232         pids = (*env)->GetLongArrayElements(env, jarray, NULL);
 233         if (pids == NULL) {
 234             break;
 235         }
 236         if (jparentArray != NULL) {
 237             ppids  = (*env)->GetLongArrayElements(env, jparentArray, NULL);
 238             if (ppids == NULL) {
 239                 break;
 240             }
 241         }
 242         if (jstimesArray != NULL) {
 243             stimes  = (*env)->GetLongArrayElements(env, jstimesArray, NULL);
 244             if (stimes == NULL) {
 245                 break;
 246             }
 247         }
 248 
 249         while ((ptr = readdir(dir)) != NULL) {
 250             pid_t ppid = 0;
 251             jlong totalTime = 0L;
 252             jlong startTime = 0L;
 253             uid_t uid; // value unused
 254 
 255             /* skip files that aren't numbers */
 256             pid_t childpid = (pid_t) atoi(ptr->d_name);
 257             if ((int) childpid <= 0) {
 258                 continue;
 259             }
 260 
 261             // Read /proc/pid/stat and get the parent pid, and start time
 262             ppid = getStatInfo(env, childpid, &totalTime, &startTime, &uid);
 263             if (ppid >= 0 && (pid == 0 || ppid == pid)) {
 264                 if (count < arraySize) {
 265                     // Only store if it fits
 266                     pids[count] = (jlong) childpid;
 267 
 268                     if (ppids != NULL) {
 269                         // Store the parent Pid
 270                         ppids[count] = (jlong) ppid;
 271                     }
 272                     if (stimes != NULL) {
 273                         // Store the process start time
 274                         stimes[count] = startTime;
 275                     }
 276                 }
 277                 count++; // Count to tabulate size needed
 278             }
 279         }
 280     } while (0);
 281 
 282     if (pids != NULL) {
 283         (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
 284     }
 285     if (ppids != NULL) {
 286         (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
 287     }
 288     if (stimes != NULL) {
 289         (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
 290     }
 291 
 292     closedir(dir);
 293     // If more pids than array had size for; count will be greater than array size
 294     return count;
 295 }
 296 
 297 /**************************************************************
 298  * Implementation of ProcessHandleImpl_Info native methods.
 299  */
 300 
 301 /*
 302  * Fill in the Info object from the OS information about the process.
 303  *
 304  * Class:     java_lang_ProcessHandleImpl_Info
 305  * Method:    info0
 306  * Signature: (J)V
 307  */
 308 JNIEXPORT void JNICALL
 309 Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
 310                                                  jobject jinfo,
 311                                                   jlong jpid) {
 312     pid_t pid = (pid_t) jpid;
 313     jlong startTime = 0L;
 314     jlong totalTime = 0L;
 315     uid_t uid = -1;
 316     pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
 317 
 318     getCmdlineInfo(env, jinfo, pid);
 319 
 320     if (ppid > 0) {
 321         jstring str;
 322         (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
 323         JNU_CHECK_EXCEPTION(env);
 324 
 325         (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
 326         JNU_CHECK_EXCEPTION(env);
 327 
 328         CHECK_NULL((str = uidToUser(env, uid)));
 329         (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, str);
 330         JNU_CHECK_EXCEPTION(env);
 331     }
 332 }
 333 
 334 /**
 335  * Read /proc/<pid>/status and return the ppid, total cputime and start time.
 336  * Return: -1 is fail;  zero is unknown; >  0 is parent pid
 337  */
 338 static pid_t getStatInfo(JNIEnv *env, pid_t pid,
 339                                       jlong *totalTime, jlong* startTime,
 340                                       uid_t* uid) {
 341     FILE* fp;
 342     psinfo_t psinfo;
 343     char fn[32];
 344     int ret;
 345 
 346     /*
 347      * Try to open /proc/%d/status
 348      */
 349     snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid);
 350     fp = fopen(fn, "r");
 351     if (fp == NULL) {
 352         return -1;
 353     }
 354 
 355     ret = fread(&psinfo, 1, (sizeof psinfo), fp);
 356     fclose(fp);
 357     if (ret < (sizeof psinfo)) {
 358         return -1;
 359     }
 360 
 361     *totalTime = psinfo.pr_time.tv_sec * 1000000000L + psinfo.pr_time.tv_nsec;
 362 
 363     *startTime = psinfo.pr_start.tv_sec * (jlong)1000 +
 364                  psinfo.pr_start.tv_nsec / 1000000;
 365 
 366     *uid = psinfo.pr_uid;
 367 
 368     return (pid_t) psinfo.pr_ppid;
 369 }
 370 
 371 static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
 372     char fn[32];
 373     char exePath[PATH_MAX];
 374     jstring str = NULL;
 375     int ret;
 376 
 377     /*
 378      * The path to the executable command is the link in /proc/<pid>/paths/a.out.
 379      */
 380     snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
 381     if ((ret = readlink(fn, exePath, PATH_MAX - 1)) < 0) {
 382         return;
 383     }
 384 
 385     // null terminate and create String to store for command
 386     exePath[ret] = '\0';
 387     CHECK_NULL(str = JNU_NewStringPlatform(env, exePath));
 388     (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
 389     JNU_CHECK_EXCEPTION(env);
 390 }
 391 


  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "jni_util.h"
  28 #include "java_lang_ProcessHandleImpl.h"
  29 #include "java_lang_ProcessHandleImpl_Info.h"
  30 
  31 #include "ProcessHandleImpl_unix.h"
  32 
  33 
  34 #include <stdio.h>




  35 #include <procfs.h>


































































































































  36 
  37 /*
  38  * Implementation of native ProcessHandleImpl functions for Solaris.
  39  * See ProcessHandleImpl_unix.c for more details.








  40  */


















  41 
  42 void os_initNative(JNIEnv *env, jclass clazz) {}




  43 
  44 uid_t os_getUID(pid_t pid) {
  45     return unix_getUID(pid);























































































  46 }
  47 
  48 jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
  49                     jlongArray jparentArray, jlongArray jstimesArray) {
  50     return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
































  51 }
  52 
  53 pid_t os_getParentPid(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
  54     return unix_getParentPid(env, pid, total, start);

































  55 }
  56 
  57 void os_getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
  58     unix_getCmdlineInfo(env, jinfo, pid);

















  59 }
  60 
< prev index next >