Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

filelock fails to acquire lock in sub-process launched via callr? #32

Closed
kevinushey opened this issue Feb 12, 2021 · 7 comments
Closed

Comments

@kevinushey
Copy link

library(callr)
library(filelock)

file <- tempfile("lockfile-")
filelock::lock(file)
#> Lock on '/private/tmp/Rtmp3hJ9XM/lockfile-1009c4e2ac322'

callr::r(function() {
  file <- tempfile("lockfile-")
  filelock::lock(file)
})
#> Unlocked lock on '/private/tmp/Rtmpr7Jryb/lockfile-100aa7989c5ff'

Created on 2021-02-12 by the reprex package (v1.0.0)

Is this the expected behavior?

@kevinushey
Copy link
Author

With this script I see the expected behavior:

library(filelock)

# acquire lock in this process
file <- tempfile("lockfile-")
lock <- filelock::lock(file)
print(lock)

# try acquiring lock on same file in sub-process
code <- substitute({
  library(filelock)
  lock <- filelock::lock(file, timeout = 0)
  if (is.null(lock))
    stop("failed to acquire lock")
}, list(file = file))

# write to separate script and run
script <- tempfile("lock-", fileext = ".R")
writeLines(deparse(code), con = script)
R <- file.path(R.home("bin"), "R")
system2(R, c("-s", "-f", shQuote(script)))

That is:

> system2(R, c("-s", "-f", shQuote(script)))
Error: failed to acquire lock
Execution halted

@gaborcsardi
Copy link
Member

gaborcsardi commented Feb 12, 2021

A lock is an external pointer, you cannot copy it to another process. A lock belongs to a process, in the first place.

Locking in a sub-process does work of course, many filelock test cases are written that way, actually.

What is the problem you want to solve?

@kevinushey
Copy link
Author

Sorry, this was my mistake 😞 . In this:

callr::r(function() {
  file <- tempfile("lockfile-")
  filelock::lock(file)
})
#> Unlocked lock on '/private/tmp/Rtmpr7Jryb/lockfile-100aa7989c5ff'

I thought the output here was from within the sub-process; that is, I thought the sub-process was reporting that the lock wasn't actually acquired. This makes it clear that everything is working as intended:

> callr::r(function() {
+   file <- tempfile("lockfile-")
+   capture.output(print(filelock::lock(file)))
+ })
[1] "Lock on ‘/private/tmp/RtmpJT8T2e/lockfile-1084646fed2ed’"

Ultimately, my goal here was to provide a user with some test code using the filelock package to see if advisory locks were working as expected on their NFS volume...

@gaborcsardi
Copy link
Member

Ultimately, my goal here was to provide a user with some test code using the filelock package to see if advisory locks were working as expected on their NFS volume...

Did they? My understanding is that on recent Linux kernels they should.

@kevinushey
Copy link
Author

Evidently so, although in this case it was a user on macOS. We've seen issues with advisory file locks not working on some specific NFS instances either because they were too old or misconfigured in some way, though.

@gaborcsardi
Copy link
Member

Do you think it would be useful to detect when advisory locks are not working, and fall back to another mechanism?

@kevinushey
Copy link
Author

That could be useful. For what it's worth, In RStudio, we have a separate locking scheme that relies on the atomicity of ::link(), which should be atomic even for older NFS systems. (Handling "stale" or "orphaned" locks becomes more challenging though)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants