diff options
| author | 2024-07-24 22:55:23 +0000 | |
|---|---|---|
| committer | 2024-07-24 22:55:23 +0000 | |
| commit | eadf19f00ffeae7179107d41d131ea44997e5540 (patch) | |
| tree | b505a88ca97e8159a0d057725b83e4225acab1f1 | |
| parent | 694948c0770be004886299244f8e07da50150664 (diff) | |
| parent | c90540ca1aecb757f36623494373f0e5dec854c3 (diff) | |
Merge changes I95ebeb36,I37da934b,Ifa4a739c,I3d8e5c72,If6a14c4e into main am: c90540ca1a
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/3185048
Change-Id: I46f8c668f7ecbf3481450653ef6f54400b54eeb7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
| -rw-r--r-- | core/jni/android_util_Process.cpp | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 1a1d83cb6fb6..4cc904153aac 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -33,6 +33,7 @@ #include <algorithm> #include <array> +#include <cstring> #include <limits> #include <memory> #include <string> @@ -50,7 +51,6 @@ #include <inttypes.h> #include <pwd.h> #include <signal.h> -#include <string.h> #include <sys/epoll.h> #include <sys/errno.h> #include <sys/pidfd.h> @@ -73,13 +73,13 @@ static constexpr bool kDebugProc = false; // readProcFile() are reading files under this threshold, e.g., // /proc/pid/stat. /proc/pid/time_in_state ends up being about 520 // bytes, so use 1024 for the stack to provide a bit of slack. -static constexpr ssize_t kProcReadStackBufferSize = 1024; +static constexpr size_t kProcReadStackBufferSize = 1024; // The other files we read from proc tend to be a bit larger (e.g., // /proc/stat is about 3kB), so once we exhaust the stack buffer, // retry with a relatively large heap-allocated buffer. We double // this size and retry until the whole file fits. -static constexpr ssize_t kProcReadMinHeapBufferSize = 4096; +static constexpr size_t kProcReadMinHeapBufferSize = 4096; #if GUARD_THREAD_PRIORITY Mutex gKeyCreateMutex; @@ -818,7 +818,6 @@ jintArray android_os_Process_getPids(JNIEnv* env, jobject clazz, } DIR* dirp = opendir(file8); - env->ReleaseStringUTFChars(file, file8); if(dirp == NULL) { @@ -851,6 +850,7 @@ jintArray android_os_Process_getPids(JNIEnv* env, jobject clazz, jintArray newArray = env->NewIntArray(newCount); if (newArray == NULL) { closedir(dirp); + if (curData) env->ReleaseIntArrayElements(lastArray, curData, 0); jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return NULL; } @@ -1047,78 +1047,71 @@ jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz, return JNI_FALSE; } - const char* file8 = env->GetStringUTFChars(file, NULL); - if (file8 == NULL) { + auto releaser = [&](const char* jniStr) { env->ReleaseStringUTFChars(file, jniStr); }; + std::unique_ptr<const char[], decltype(releaser)> file8(env->GetStringUTFChars(file, NULL), + releaser); + if (!file8) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return JNI_FALSE; } - ::android::base::unique_fd fd(open(file8, O_RDONLY | O_CLOEXEC)); + ::android::base::unique_fd fd(open(file8.get(), O_RDONLY | O_CLOEXEC)); if (!fd.ok()) { if (kDebugProc) { - ALOGW("Unable to open process file: %s\n", file8); + ALOGW("Unable to open process file: %s\n", file8.get()); } - env->ReleaseStringUTFChars(file, file8); return JNI_FALSE; } - env->ReleaseStringUTFChars(file, file8); // Most proc files we read are small, so we go through the loop - // with the stack buffer firstly. We allocate a buffer big - // enough for the whole file. - - char readBufferStack[kProcReadStackBufferSize]; - std::unique_ptr<char[]> readBufferHeap; - char* readBuffer = &readBufferStack[0]; - ssize_t readBufferSize = kProcReadStackBufferSize; - ssize_t numberBytesRead; + // with the stack buffer first. We allocate a buffer big enough + // for most files. + + char stackBuf[kProcReadStackBufferSize]; + std::vector<char> heapBuf; + char* buf = stackBuf; + + size_t remaining = sizeof(stackBuf); off_t offset = 0; - for (;;) { - ssize_t requestedBufferSize = readBufferSize - offset; - // By using pread, we can avoid an lseek to rewind the FD - // before retry, saving a system call. - numberBytesRead = - TEMP_FAILURE_RETRY(pread(fd, readBuffer + offset, requestedBufferSize, offset)); - if (numberBytesRead < 0) { + ssize_t numBytesRead; + + do { + numBytesRead = TEMP_FAILURE_RETRY(pread(fd, buf + offset, remaining, offset)); + if (numBytesRead < 0) { if (kDebugProc) { ALOGW("Unable to read process file err: %s file: %s fd=%d\n", - strerror_r(errno, &readBufferStack[0], sizeof(readBufferStack)), file8, - fd.get()); + strerror_r(errno, stackBuf, sizeof(stackBuf)), file8.get(), fd.get()); } return JNI_FALSE; } - if (numberBytesRead == 0) { - // End of file. - numberBytesRead = offset; - break; - } - if (numberBytesRead < requestedBufferSize) { - // Read less bytes than requested, it's not an error per pread(2). - offset += numberBytesRead; - } else { - // Buffer is fully used, try to grow it. - if (readBufferSize > std::numeric_limits<ssize_t>::max() / 2) { - if (kDebugProc) { - ALOGW("Proc file too big: %s fd=%d\n", file8, fd.get()); + + offset += numBytesRead; + remaining -= numBytesRead; + + if (numBytesRead && !remaining) { + if (buf == stackBuf) { + heapBuf.resize(kProcReadMinHeapBufferSize); + static_assert(kProcReadMinHeapBufferSize > sizeof(stackBuf)); + std::memcpy(heapBuf.data(), stackBuf, sizeof(stackBuf)); + } else { + constexpr size_t MAX_READABLE_PROCFILE_SIZE = 64 << 20; + if (heapBuf.size() >= MAX_READABLE_PROCFILE_SIZE) { + if (kDebugProc) { + ALOGW("Proc file too big: %s fd=%d size=%zu\n", + file8.get(), fd.get(), heapBuf.size()); + } + return JNI_FALSE; } - return JNI_FALSE; - } - readBufferSize = std::max(readBufferSize * 2, kProcReadMinHeapBufferSize); - readBufferHeap.reset(); // Free address space before getting more. - readBufferHeap = std::make_unique<char[]>(readBufferSize); - if (!readBufferHeap) { - jniThrowException(env, "java/lang/OutOfMemoryError", NULL); - return JNI_FALSE; + heapBuf.resize(2 * heapBuf.size()); } - readBuffer = readBufferHeap.get(); - offset = 0; + buf = heapBuf.data(); + remaining = heapBuf.size() - offset; } - } + } while (numBytesRead != 0); // parseProcLineArray below modifies the buffer while parsing! return android_os_Process_parseProcLineArray( - env, clazz, readBuffer, 0, numberBytesRead, - format, outStrings, outLongs, outFloats); + env, clazz, buf, 0, offset, format, outStrings, outLongs, outFloats); } void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz, |