Skip to content

Commit e62ccbf

Browse files
committed
YJIT: ZJIT: Abort faster when OOM in rb_jit_reserve_addr_space
Previously, the loop condition checked the wrong direction so required wrapping around the address space to break out the loop. It takes a few seconds to do a few million mmap calls then loop around and then crash. A way to test this is by experimenting with different values of `ulimit -v`. Try 400,000 and up. Explicitly bound the loop. Also rotate the loop so we don't waste the first probe which was done with a mapped address. Fixes: b215a35
1 parent 2b3a89a commit e62ccbf

1 file changed

Lines changed: 17 additions & 11 deletions

File tree

jit.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,25 @@ rb_jit_reserve_addr_space(uint32_t mem_size)
734734
#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
735735
uint32_t const page_size = (uint32_t)sysconf(_SC_PAGESIZE);
736736
uint8_t *const cfunc_sample_addr = (void *)(uintptr_t)&rb_jit_reserve_addr_space;
737-
uint8_t *const probe_region_end = cfunc_sample_addr + INT32_MAX;
738-
// Align the requested address to page size
739-
uint8_t *req_addr = align_ptr(cfunc_sample_addr, page_size);
737+
// 64MiB. This is rather arbitrary.
738+
const uintptr_t probe_stride = 64 * 1024 * 1024;
739+
// Related to the stride. Any successful trial will be within INT32_MAX
740+
// range with slack for the binary size.
741+
const int max_probe_trials = 30;
740742

741743
// Probe for addresses close to this function using MAP_FIXED_NOREPLACE
742744
// to improve odds of being in range for 32-bit relative call instructions.
743-
do {
745+
uint8_t *req_addr = cfunc_sample_addr;
746+
for (int i = 0; i < max_probe_trials; i++) {
747+
// Downwards to probe away from the heap. (On x86/A64 Linux
748+
// main_code_addr < heap_addr, and in case we are in a shared
749+
// library mapped higher than the heap, downwards is still better
750+
// since it's towards the end of the heap rather than the stack.)
751+
req_addr -= probe_stride;
752+
753+
// Align the requested address to page size
754+
req_addr = align_ptr(req_addr, page_size);
755+
744756
mem_block = mmap(
745757
req_addr,
746758
mem_size,
@@ -755,13 +767,7 @@ rb_jit_reserve_addr_space(uint32_t mem_size)
755767
ruby_annotate_mmap(mem_block, mem_size, "Ruby:rb_jit_reserve_addr_space");
756768
break;
757769
}
758-
759-
// -4MiB. Downwards to probe away from the heap. (On x86/A64 Linux
760-
// main_code_addr < heap_addr, and in case we are in a shared
761-
// library mapped higher than the heap, downwards is still better
762-
// since it's towards the end of the heap rather than the stack.)
763-
req_addr -= 4 * 1024 * 1024;
764-
} while (req_addr < probe_region_end);
770+
}
765771

766772
// On MacOS and other platforms
767773
#else

0 commit comments

Comments
 (0)