@@ -264,9 +264,9 @@ static void *alloc_shared_page(size_t size, size_t *id, bool exec)
264
264
#ifdef _OS_LINUX_
265
265
// Using `/proc/self/mem`, A.K.A. Keno's remote memory manager.
266
266
267
- static int self_mem_fd = - 1 ;
268
-
269
- static int init_self_mem ()
267
+ // Do not call this directly.
268
+ // Use `get_self_mem_fd` which has a guard to call this only once.
269
+ static int _init_self_mem ()
270
270
{
271
271
struct utsname kernel;
272
272
uname (&kernel);
@@ -288,22 +288,34 @@ static int init_self_mem()
288
288
return -1 ;
289
289
fcntl (fd, F_SETFD, FD_CLOEXEC);
290
290
#endif
291
- // buffer to check if write works;
292
- volatile uint64_t buff = 0 ;
293
- uint64_t v = 0x12345678 ;
294
- int ret = pwrite (fd, (void *)&v, sizeof (uint64_t ), (uintptr_t )&buff);
295
- if (ret != sizeof (uint64_t ) || buff != 0x12345678 ) {
291
+
292
+ // Check if we can write to a RX page
293
+ void *test_pg = mmap (nullptr , jl_page_size, PROT_READ | PROT_EXEC,
294
+ MAP_PRIVATE | MAP_ANONYMOUS, -1 , 0 );
295
+ // We can ignore this though failure to allocate executable memory would be a bigger problem.
296
+ assert (test_pg != MAP_FAILED && " Cannot allocate executable memory" );
297
+
298
+ const uint64_t v = 0xffff000012345678u ;
299
+ int ret = pwrite (fd, (const void *)&v, sizeof (uint64_t ), (uintptr_t )test_pg);
300
+ if (ret != sizeof (uint64_t ) || *(volatile uint64_t *)test_pg != v) {
301
+ munmap (test_pg, jl_page_size);
296
302
close (fd);
297
303
return -1 ;
298
304
}
299
- self_mem_fd = fd;
305
+ munmap (test_pg, jl_page_size);
306
+ return fd;
307
+ }
308
+
309
+ static int get_self_mem_fd ()
310
+ {
311
+ static int fd = _init_self_mem ();
300
312
return fd;
301
313
}
302
314
303
315
static void write_self_mem (void *dest, void *ptr, size_t size)
304
316
{
305
317
while (size > 0 ) {
306
- ssize_t ret = pwrite (self_mem_fd , ptr, size, (uintptr_t )dest);
318
+ ssize_t ret = pwrite (get_self_mem_fd () , ptr, size, (uintptr_t )dest);
307
319
if ((size_t )ret == size)
308
320
return ;
309
321
if (ret == -1 && (errno == EAGAIN || errno == EINTR))
@@ -657,7 +669,7 @@ class SelfMemAllocator : public ROAllocator<exec> {
657
669
: ROAllocator<exec>(),
658
670
temp_buff ()
659
671
{
660
- assert (self_mem_fd != -1 );
672
+ assert (get_self_mem_fd () != -1 );
661
673
}
662
674
void finalize () override
663
675
{
@@ -717,7 +729,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
717
729
code_allocated(false )
718
730
{
719
731
#ifdef _OS_LINUX_
720
- if (!ro_alloc && init_self_mem () != -1 ) {
732
+ if (!ro_alloc && get_self_mem_fd () != -1 ) {
721
733
ro_alloc.reset (new SelfMemAllocator<false >());
722
734
exe_alloc.reset (new SelfMemAllocator<true >());
723
735
}
0 commit comments