8315026: ProcessHandle implementation listing processes on AIX should use getprocs64

Reviewed-by: rriggs, stuefe, mbaesken
This commit is contained in:
Joachim Kern 2023-10-13 08:29:48 +00:00 committed by Matthias Baesken
parent 1082c0e767
commit 4d9042043e
2 changed files with 139 additions and 9 deletions
src/java.base
aix/native/libjava
unix/native/libjava

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,10 +24,12 @@
*/
#include "jni.h"
#include "jni_util.h"
#include "ProcessHandleImpl_unix.h"
#include <sys/procfs.h>
#include <procinfo.h>
/*
* Implementation of native ProcessHandleImpl functions for AIX.
@ -36,9 +38,127 @@
void os_initNative(JNIEnv *env, jclass clazz) {}
/*
* Return pids of active processes, and optionally parent pids and
* start times for each process.
* For a specific non-zero pid, only the direct children are returned.
* If the pid is zero, all active processes are returned.
* Use getprocs64 to accumulate any process following the rules above.
* The resulting pids are stored into an array of longs named jarray.
* The number of pids is returned if they all fit.
* If the parentArray is non-null, store also the parent pid.
* In this case the parentArray must have the same length as the result pid array.
* Of course in the case of a given non-zero pid all entries in the parentArray
* will contain this pid, so this array does only make sense in the case of a given
* zero pid.
* If the jstimesArray is non-null, store also the start time of the pid.
* In this case the jstimesArray must have the same length as the result pid array.
* If the array(s) (is|are) too short, excess pids are not stored and
* the desired length is returned.
*/
jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
jlongArray jparentArray, jlongArray jstimesArray) {
return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
pid_t pid = (pid_t) jpid;
jlong* pids = NULL;
jlong* ppids = NULL;
jlong* stimes = NULL;
jsize parentArraySize = 0;
jsize arraySize = 0;
jsize stimesSize = 0;
jsize count = 0;
arraySize = (*env)->GetArrayLength(env, jarray);
JNU_CHECK_EXCEPTION_RETURN(env, -1);
if (jparentArray != NULL) {
parentArraySize = (*env)->GetArrayLength(env, jparentArray);
JNU_CHECK_EXCEPTION_RETURN(env, -1);
if (arraySize != parentArraySize) {
JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
return 0;
}
}
if (jstimesArray != NULL) {
stimesSize = (*env)->GetArrayLength(env, jstimesArray);
JNU_CHECK_EXCEPTION_RETURN(env, -1);
if (arraySize != stimesSize) {
JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
return 0;
}
}
const int chunk = 100;
struct procentry64 ProcessBuffer[chunk];
pid_t idxptr = 0;
int i, num = 0;
do { // Block to break out of on Exception
pids = (*env)->GetLongArrayElements(env, jarray, NULL);
if (pids == NULL) {
break;
}
if (jparentArray != NULL) {
ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL);
if (ppids == NULL) {
break;
}
}
if (jstimesArray != NULL) {
stimes = (*env)->GetLongArrayElements(env, jstimesArray, NULL);
if (stimes == NULL) {
break;
}
}
while ((num = getprocs64(ProcessBuffer, sizeof(struct procentry64), NULL,
sizeof(struct fdsinfo64), &idxptr, chunk)) != -1) {
for (i = 0; i < num; i++) {
pid_t childpid = (pid_t) ProcessBuffer[i].pi_pid;
pid_t ppid = (pid_t) ProcessBuffer[i].pi_ppid;
// Get the parent pid, and start time
if (pid == 0 || ppid == pid) {
if (count < arraySize) {
// Only store if it fits
pids[count] = (jlong) childpid;
if (ppids != NULL) {
// Store the parentPid
ppids[count] = (jlong) ppid;
}
if (stimes != NULL) {
// Store the process start time
stimes[count] = ((jlong) ProcessBuffer[i].pi_start) * 1000;;
}
}
count++; // Count to tabulate size needed
}
}
if (num < chunk) {
break;
}
}
} while (0);
if (pids != NULL) {
(*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
}
if (ppids != NULL) {
(*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
}
if (stimes != NULL) {
(*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
}
if (num == -1) {
JNU_ThrowByNameWithLastError(env,
"java/lang/RuntimeException", "Unable to retrieve Process info");
return -1;
}
// If more pids than array had size for; count will be greater than array size
return count;
}
pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {

@ -488,15 +488,25 @@ void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid) {
* The following functions are common on Solaris, Linux and AIX.
*/
#if defined (__linux__) || defined(_AIX)
#if defined (__linux__)
/*
* Returns the children of the requested pid and optionally each parent and
* start time.
* Reads /proc and accumulates any process who parent pid matches.
* The resulting pids are stored into the array of longs.
* Return pids of active processes, and optionally parent pids and
* start times for each process.
* For a specific non-zero pid, only the direct children are returned.
* If the pid is zero, all active processes are returned.
* Reads /proc and accumulates any process following the rules above.
* The resulting pids are stored into an array of longs named jarray.
* The number of pids is returned if they all fit.
* If the array is too short, the negative of the desired length is returned.
* If the parentArray is non-null, store also the parent pid.
* In this case the parentArray must have the same length as the result pid array.
* Of course in the case of a given non-zero pid all entries in the parentArray
* will contain this pid, so this array does only make sense in the case of a given
* zero pid.
* If the jstimesArray is non-null, store also the start time of the pid.
* In this case the jstimesArray must have the same length as the result pid array.
* If the array(s) (is|are) too short, excess pids are not stored and
* the desired length is returned.
*/
jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
jlongArray jparentArray, jlongArray jstimesArray) {
@ -607,7 +617,7 @@ jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
return count;
}
#endif // defined (__linux__) || defined(_AIX)
#endif // defined (__linux__)
/*
* The following functions are for AIX.