Switch to using fcntl from flock on unix

This commit is contained in:
Caelan Sayler
2024-11-03 11:59:51 +00:00
committed by Caelan
parent 2946b4ea2c
commit a173b33aaf
2 changed files with 77 additions and 18 deletions

View File

@@ -55,27 +55,77 @@ namespace Velopack.Util
}
}
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
[DllImport("libc", SetLastError = true)]
private static extern int flock(int fd, int operation);
private const int LOCK_SH = 1; // Shared lock
private const int LOCK_EX = 2; // Exclusive lock
private const int LOCK_NB = 4; // Non-blocking
private const int LOCK_UN = 8; // Unlock
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")]
private void UnixExclusiveLock(int fd)
{
int ret = flock(fd, LOCK_EX | LOCK_NB);
if (ret != 0) {
throw new IOException("flock returned error: " + ret);
int ret;
if (VelopackRuntimeInfo.IsLinux) {
var lockOpt = new linux_flock {
l_type = F_WRLCK,
l_whence = SEEK_SET,
l_start = 0,
l_len = 0, // 0 means to lock the entire file
l_pid = 0,
};
ret = fcntl(fd, F_SETLK, ref lockOpt);
} else if (VelopackRuntimeInfo.IsOSX) {
var lockOpt = new osx_flock {
l_start = 0,
l_len = 0, // 0 means to lock the entire file
l_pid = 0,
l_type = F_WRLCK,
l_whence = SEEK_SET,
};
Console.WriteLine("hello");
ret = fcntl(fd, F_SETLK, ref lockOpt);
} else {
throw new PlatformNotSupportedException();
}
Console.WriteLine(ret);
if (ret == -1) {
int errno = Marshal.GetLastWin32Error();
throw new IOException($"fcntl F_SETLK failed, errno: {errno}", new Win32Exception(errno));
}
}
[SupportedOSPlatform("linux")]
[DllImport("libc", SetLastError = true)]
private static extern int fcntl(int fd, int cmd, ref linux_flock linux_flock);
[SupportedOSPlatform("macos")]
[DllImport("libc", SetLastError = true)]
private static extern int fcntl(int fd, int cmd, ref osx_flock linux_flock);
[SupportedOSPlatform("linux")]
[StructLayout(LayoutKind.Sequential)]
private struct linux_flock
{
public short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */
public short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
public long l_start; /* Starting offset for lock */
public long l_len; /* Number of bytes to lock */
public int l_pid; /* PID of the process blocking our lock (F_GETLK only) */
}
[SupportedOSPlatform("macos")]
[StructLayout(LayoutKind.Sequential)]
private struct osx_flock
{
public long l_start; /* Starting offset for lock */
public long l_len; /* Number of bytes to lock */
public int l_pid; /* PID of the process blocking our lock (F_GETLK only) */
public short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */
public short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
}
private const int F_SETLK = 6; /* Non-blocking lock */
private const short F_RDLCK = 0; /* Read lock */
private const short F_WRLCK = 1; /* Write lock */
private const short F_UNLCK = 2; /* Remove lock */
private const short SEEK_SET = 0;
[SupportedOSPlatform("windows")]
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool LockFileEx(SafeFileHandle hFile, uint dwFlags, uint dwReserved, uint nNumberOfBytesToLockLow, uint nNumberOfBytesToLockHigh,

View File

@@ -35,7 +35,7 @@ impl LockFile {
{
use std::os::unix::io::AsRawFd;
let fd = file.as_raw_fd();
self.unix_exclusive_lock(fd)?;
lock_file.unix_exclusive_lock(fd)?;
}
#[cfg(target_os = "windows")]
@@ -60,10 +60,19 @@ impl LockFile {
/// Acquires an exclusive, non-blocking lock on Unix-like systems.
#[cfg(unix)]
fn unix_exclusive_lock(&self, fd: std::os::unix::io::RawFd) -> Result<()> {
use libc::{flock, LOCK_EX, LOCK_NB};
use libc::{fcntl, F_SETLK, F_WRLCK, SEEK_SET};
let ret = unsafe { flock(fd, LOCK_EX | LOCK_NB) };
if ret != 0 {
let lock = libc::flock {
l_type: F_WRLCK as libc::c_short,
l_whence: SEEK_SET as libc::c_short,
l_start: 0,
l_len: 0, // 0 means to lock the entire file
l_pid: 0,
};
let ret = unsafe { fcntl(fd, F_SETLK, &lock) };
if ret == -1 {
let err = Error::last_os_error();
Err(Error::new(
ErrorKind::Other,