Skip to content

Commit 978075f

Browse files
committed
8339487: ProcessHandleImpl os_getChildren sysctl call - retry in case of ENOMEM and enhance exception message
Backport-of: 4ff72dc57e65e99b129f0ba28196994edf402018
1 parent 7fd462f commit 978075f

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

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

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,25 +97,35 @@ jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
9797
}
9898
}
9999

100-
// Get buffer size needed to read all processes
101-
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
102-
if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) {
103-
JNU_ThrowByNameWithLastError(env,
104-
"java/lang/RuntimeException", "sysctl failed");
105-
return -1;
106-
}
100+
int errsysctl;
101+
int maxRetries = 100;
102+
void *buffer = NULL;
103+
do {
104+
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
105+
if (buffer != NULL) free(buffer);
106+
// Get buffer size needed to read all processes
107+
if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) {
108+
JNU_ThrowByNameWithMessageAndLastError(env,
109+
"java/lang/RuntimeException", "sysctl failed");
110+
return -1;
111+
}
107112

108-
// Allocate buffer big enough for all processes
109-
void *buffer = malloc(bufSize);
110-
if (buffer == NULL) {
111-
JNU_ThrowOutOfMemoryError(env, "malloc failed");
112-
return -1;
113-
}
113+
// Allocate buffer big enough for all processes; add a little
114+
// bit of space to be able to hold a few more proc infos
115+
// for processes started right after the first sysctl call
116+
buffer = malloc(bufSize + 4 * sizeof(struct kinfo_proc));
117+
if (buffer == NULL) {
118+
JNU_ThrowOutOfMemoryError(env, "malloc failed");
119+
return -1;
120+
}
114121

115-
// Read process info for all processes
116-
if (sysctl(mib, 4, buffer, &bufSize, NULL, 0) < 0) {
117-
JNU_ThrowByNameWithLastError(env,
118-
"java/lang/RuntimeException", "sysctl failed");
122+
// Read process info for all processes
123+
errsysctl = sysctl(mib, 4, buffer, &bufSize, NULL, 0);
124+
} while (errsysctl < 0 && errno == ENOMEM && maxRetries-- > 0);
125+
126+
if (errsysctl < 0) {
127+
JNU_ThrowByNameWithMessageAndLastError(env,
128+
"java/lang/RuntimeException", "sysctl failed to get info about all processes");
119129
free(buffer);
120130
return -1;
121131
}

src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
547547
* position integer as a filename.
548548
*/
549549
if ((dir = opendir("/proc")) == NULL) {
550-
JNU_ThrowByNameWithLastError(env,
550+
JNU_ThrowByNameWithMessageAndLastError(env,
551551
"java/lang/RuntimeException", "Unable to open /proc");
552552
return -1;
553553
}

0 commit comments

Comments
 (0)