Skip to content

Commit

Permalink
Handle EPERM errors when opening files with O_NOATIME.
Browse files Browse the repository at this point in the history
```
       EPERM  The O_NOATIME flag was specified, but the effective user
              ID of the caller did not match the owner of the file and
              the caller was not privileged.
```
  • Loading branch information
byroot committed Jan 30, 2024
1 parent efb56e4 commit 4dd0c77
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

* Handle `EPERM` errors when opening files with `O_NOATIME`.

# 1.18.0

* `Bootsnap.instrumentation` now receive `:hit` events.
Expand Down
28 changes: 23 additions & 5 deletions ext/bootsnap/bootsnap.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ static ID instrumentation_method;
static VALUE sym_hit, sym_miss, sym_stale, sym_revalidated;
static bool instrumentation_enabled = false;
static bool readonly = false;
static bool perm_issue = false;

/* Functions exposed as module functions on Bootsnap::CompileCache::Native */
static VALUE bs_instrumentation_enabled_set(VALUE self, VALUE enabled);
Expand All @@ -119,7 +120,7 @@ static int update_cache_key(struct bs_cache_key *current_key, int cache_fd, cons
static void bs_cache_key_digest(struct bs_cache_key * key, const VALUE input_data);
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args);
static VALUE bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler);
static int open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance);
static int open_current_file(const char * path, struct bs_cache_key * key, const char ** errno_provenance);
static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance);
static uint32_t get_ruby_revision(void);
static uint32_t get_ruby_platform(void);
Expand Down Expand Up @@ -413,17 +414,34 @@ bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)

return bs_precompile(path, path_v, cache_path, handler);
}

static int bs_open_noatime(const char *path, int flags) {
int fd = 1;
if (!perm_issue) {
fd = open(path, flags | O_NOATIME);
if (fd < 0 && errno == EPERM) {
errno = 0;
perm_issue = true;
}
}

if (perm_issue) {
fd = open(path, flags);
}
return fd;
}

/*
* Open the file we want to load/cache and generate a cache key for it if it
* was loaded.
*/
static int
open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance)
open_current_file(const char * path, struct bs_cache_key * key, const char ** errno_provenance)
{
struct stat statbuf;
int fd;

fd = open(path, O_RDONLY | O_NOATIME);
fd = bs_open_noatime(path, O_RDONLY);
if (fd < 0) {
*errno_provenance = "bs_fetch:open_current_file:open";
return fd;
Expand Down Expand Up @@ -491,9 +509,9 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
int fd, res;

if (readonly) {
fd = open(path, O_RDONLY | O_NOATIME);
fd = bs_open_noatime(path, O_RDONLY);
} else {
fd = open(path, O_RDWR | O_NOATIME);
fd = bs_open_noatime(path, O_RDWR);
}

if (fd < 0) {
Expand Down

0 comments on commit 4dd0c77

Please sign in to comment.