Large page use crashes the JVM on some Linux systems
B. Blaser
bsrbnd at gmail.com
Wed May 9 19:08:22 UTC 2018
On 2 May 2018 at 10:38, B. Blaser <bsrbnd at gmail.com> wrote:
> Hi Claes,
>
> On 24 April 2018 at 21:39, Claes Redestad <claes.redestad at oracle.com> wrote:
>> The root issue here could very well be that the SHM sanity test is
>> insufficient. Adding the same test as we already do for TLBFS seems like the
>> wrong approach.
>>
>> I'm not the most knowledgeable about SHM, though, in fact not knowledgeable
>> at all, so let's try and get you subscribed to hotspot-dev and spark a
>> discussion on the list.
>>
>> /Claes
Experimenting on different systems, I note that the following test (
'shmget(SHM_HUGETLB) == -1' ) isn't always reliable:
http://hg.openjdk.java.net/jdk/jdk/file/35b22ca681d1/src/hotspot/os/linux/os_linux.cpp#l3709
It may happen that small pages are used when no huge pages are
available resulting in a further JVM crash due to a
non-huge-page-size-alignment of the allocated memory, as discussed
previously.
It seems that the test above could be enforced by verifying that 'size
<= (free+surplus-reserved)*hugepagesize' according to [1] and [2].
Here is a suggested fix for that, tier1 is OK (with 'HugePages_Total:
0') but any further testing on different configurations/systems would
be very valuable.
What do you think?
Thanks,
Bernard
[1] https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
[2] $ man 5 proc
diff -r e81481fea884 src/hotspot/os/linux/os_linux.cpp
--- a/src/hotspot/os/linux/os_linux.cpp Mon May 07 08:56:35 2018 +0200
+++ b/src/hotspot/os/linux/os_linux.cpp Wed May 09 19:10:32 2018 +0200
@@ -3617,6 +3617,37 @@
shm_warning_format(str " (error = %d)", err); \
} while (0)
+static bool shm_available(size_t bytes) {
+ size_t free = SIZE_MAX, rsvd = SIZE_MAX, surp = SIZE_MAX;
+ char line[40];
+
+ FILE *fp = fopen("/proc/meminfo", "r");
+ if (fp) {
+ while ((free == SIZE_MAX || rsvd == SIZE_MAX || surp == SIZE_MAX)
&& !feof(fp)) {
+ fgets(line, sizeof(line), fp);
+
+ if (free == SIZE_MAX && sscanf(line, "HugePages_Free: %zu", &free) == 1)
+ continue;
+
+ if (rsvd == SIZE_MAX && sscanf(line, "HugePages_Rsvd: %zu", &rsvd) == 1)
+ continue;
+
+ if (surp == SIZE_MAX && sscanf(line, "HugePages_Surp: %zu", &surp) == 1)
+ continue;
+ }
+ fclose(fp);
+ }
+
+ gid_t gid = -1;
+ if (fp = fopen("/proc/sys/vm/hugetlb_shm_group", "r")) {
+ fscanf(fp, "%u", &gid);
+ fclose(fp);
+ }
+
+ return (free+surp-rsvd)*os::large_page_size() >= bytes
+ && (!geteuid() || group_member(gid));
+}
+
static char* shmat_with_alignment(int shmid, size_t bytes, size_t alignment) {
assert(is_aligned(bytes, alignment), "Must be divisible by the alignment");
@@ -3703,6 +3734,11 @@
return NULL; // Fallback to small pages.
}
+ if (!shm_available(bytes)) {
+ shm_warning("Shared memory not available.");
+ return NULL;
+ }
+
// Create a large shared memory region to attach to based on size.
// Currently, size is the total size of the heap.
int shmid = shmget(IPC_PRIVATE, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W);
More information about the hotspot-dev
mailing list