Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

Commit

Permalink
Polyfill for using memfd_create with old glibc (#59)
Browse files Browse the repository at this point in the history
While memfd_create is old (Linux 3.17, October 2014), its glibc wrapper didn't arrive until much later (glibc 2.27, February 2018). Some systems thus still don't have the right glibc. This can cause issues both when running and when compiling moolib.

One solution is to "skip" glibc and just invoke memfd_create by issuing a syscall directly to the kernel. This just requires the kernel to be recent enough, both at compile-time and at runtime. (Though ideally one would like to be able to build on old kernels too).
  • Loading branch information
lw committed Dec 12, 2022
1 parent ddafe08 commit 06e7a3e
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/memory/memfd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,21 @@
#include <vector>

#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>

#undef assert
//#define assert(x) (bool(x) ? 0 : (printf("assert failure %s:%d\n", __FILE__, __LINE__), std::abort(), 0))
//#define assert(x) (bool(x) ? 0 : (__builtin_unreachable(), 0))
#define assert(x)

// We want to pass the MFD_CLOEXEC flag, but we can't rely on glibc exposing
// it, thus we redefine its value if needed.
#ifndef MFD_CLOEXEC
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/memfd.h
#define MFD_CLOEXEC 0x0001U
#endif

namespace rpc {

namespace memfd {
Expand All @@ -42,7 +50,18 @@ Memfd::~Memfd() {
}

Memfd Memfd::create(size_t size) {
int fd = memfd_create("Memfd", MFD_CLOEXEC);
// Invoking memfd_create via its raw syscall, instead of its glibc wrapper,
// removes any dependency on glibc (at compile-time and at runtime). It just
// requires the kernel to support it, both at runtime (obviously) but also at
// compile-time since the SYS_memfd_create value comes from the kernel, and
// cannot be polyfilled since it's architecture-dependent.
#ifdef SYS_memfd_create
int fd = static_cast<int>(
::syscall(SYS_memfd_create, static_cast<const char*>("Memfd"), static_cast<unsigned int>(MFD_CLOEXEC)));
#else // SYS_memfd_create
int fd = -1;
errno = ENOSYS;
#endif // SYS_memfd_create
if (fd == -1) {
throw std::system_error(errno, std::generic_category(), "memfd_create");
}
Expand Down

0 comments on commit 06e7a3e

Please sign in to comment.