From f344502d33fbe97ab4394377b00210c4ee46cfc5 Mon Sep 17 00:00:00 2001 From: MBaesken Date: Thu, 5 Sep 2024 15:16:53 +0200 Subject: [PATCH] Repeat sysctl in case of failures; increase the proc info buffer a bit to hold some more very recent procs --- .../native/libjava/ProcessHandleImpl_macosx.c | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c b/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c index a9bf9a8f8cb74..940d2a3a1fae1 100644 --- a/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c +++ b/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c @@ -97,23 +97,33 @@ jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray, } } - // Get buffer size needed to read all processes - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; - if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) { - JNU_ThrowByNameWithMessageAndLastError(env, - "java/lang/RuntimeException", "sysctl failed"); - return -1; - } + int errsysctl; + int maxRetries = 100; + void *buffer = NULL; + do { + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; + if (buffer != NULL) free(buffer); + // Get buffer size needed to read all processes + if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) { + JNU_ThrowByNameWithMessageAndLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + return -1; + } - // Allocate buffer big enough for all processes - void *buffer = malloc(bufSize); - if (buffer == NULL) { - JNU_ThrowOutOfMemoryError(env, "malloc failed"); - return -1; - } + // Allocate buffer big enough for all processes; add a little + // bit of space to be able to hold a few more proc infos + // for processes started rigth after the first sysctl call + buffer = malloc(bufSize + 4 * sizeof(struct kinfo_proc)); + if (buffer == NULL) { + JNU_ThrowOutOfMemoryError(env, "malloc failed"); + return -1; + } + + // Read process info for all processes + errsysctl = sysctl(mib, 4, buffer, &bufSize, NULL, 0); + } while (errsysctl < 0 && maxRetries-- > 0); - // Read process info for all processes - if (sysctl(mib, 4, buffer, &bufSize, NULL, 0) < 0) { + if (errsysctl < 0) { JNU_ThrowByNameWithMessageAndLastError(env, "java/lang/RuntimeException", "sysctl failed to get info about all processes"); free(buffer);