Context: I'm currently writing a simple library for sharing memory between Linux and Wine processes. The only way I found so far to synchronize access is locking the file, since Wine's implementation of LockFileEx
uses F_SETLK
.
The FCNTL(3P)
man page specifies that the behavior of fcntl(/*...*/, F_SETLK, /*...*/)
for shared memory is unspecified:
When the file descriptor fildes refers to a shared memory object, the behavior of fcntl() shall be the same as for a regular file except the effect of the following values for the argument cmd shall be unspecified: F_SETFL, F_GETLK, F_SETLK, and F_SETLKW.
However, FCNTL(2)
doesn't seem to mention the issue, so to test it, I wrote the following C++ program (compile with g++ -lrt test.cxx
):
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#define SHM_NAME "thisisatest"
#define BUF_SIZE 16
int main()
{
int mytest = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0600);
if (mytest < 0)
{
std::cerr << "failed to open shared memory\n";
return 1;
}
if (ftruncate(mytest, BUF_SIZE) < 0)
{
std::cerr << "failed to open shared memory\n";
close(mytest);
shm_unlink(SHM_NAME);
return 1;
}
volatile void* mytestMem = mmap(nullptr, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mytest, 0);
if (mytestMem == MAP_FAILED)
{
std::cerr << "failed to map shared memory\n";
close(mytest);
shm_unlink(SHM_NAME);
return 1;
}
std::clog << "Trying to lock first byte...\n";
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
if (fcntl(mytest, F_SETLKW, &lock) < 0)
{
std::clog << "Failed to lock.\n";
}
else
{
std::clog << "Locked.\n";
}
// Do stuff with the shared memory...
// Wait until enter is pressed
std::cin.get();
lock.l_type = F_UNLCK;
if (fcntl(mytest, F_SETLKW, &lock) < 0)
{
std::clog << "Failed to unlock.\n";
}
else
{
std::clog << "Unlocked.\n";
}
munmap(const_cast<void*>(mytestMem), BUF_SIZE);
close(mytest);
shm_unlink(SHM_NAME);
}
And it works: if I run the program twice, the second one will stop until the first unlocks the file. So I should be able to use this.
My issue is: I was unable to find confirmation anywhere whether or not this will always work. Can I rely on this behavior on Linux?