Skip to content

fs/vfs/fs_lock.c: fix behavior according to manual and support SHM#19110

Merged
lupyuen merged 2 commits into
apache:masterfrom
michallenc:shm-flock
Jun 11, 2026
Merged

fs/vfs/fs_lock.c: fix behavior according to manual and support SHM#19110
lupyuen merged 2 commits into
apache:masterfrom
michallenc:shm-flock

Conversation

@michallenc

Copy link
Copy Markdown
Contributor

Summary

Two commits:

fs/vfs/fs_lock.c: fix flock behavior for more threads and fds
We need to use gettid instead of getpid, otherwise flocks applied
from different threads are considered as single thread lock and are
ignored (or updated).

Also fix the behavior if process opens the file multiple times
Linux/BSD manual states multiple file descriptors opened by a single
process shall be treated independently. Therefore we also need to
compare struct file pointer to determine whether the lock applies
to the same descriptor or not.

fs/vfs/fs_lock.c: support flock for SHM driver
We can apply file lock on SHM inode as well. Ensure file_lock_get_path
function passes and doesn't return EBADF errno.

Impact

Fixes flock behavior according to the manual and allows the usage of the function on SHM.

Testing

Testing first commit (behavior fix) on standard files with two threads:

#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

static const char *name = "/tmp/test.txt";

static void *t(void *arg) {
	const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
	int fd = open(name, O_RDWR | O_CREAT, mode);
	int ret = flock(fd, LOCK_SH | LOCK_NB);
	printf("2: should not lock: %d\n", ret);
	sleep(1);
	ret = flock(fd, LOCK_EX);
	printf("2: should lock: %d\n", ret);

	close(fd);
	return NULL;
}

int main(int argc, char *argv[]) {
	const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
	int fd = open(name, O_RDWR | O_CREAT, mode);
	int ret = flock(fd, LOCK_SH);
	printf("1: should lock: %d\n", ret);
	ret = flock(fd, LOCK_EX);
	printf("1: should lock as EX even though locked: %d\n", ret);

	pthread_t thread;
	pthread_create(&thread, NULL, t, NULL);

	sleep(5);
	ret = flock(fd, LOCK_UN);
	printf("1: should unlock: %d\n", ret);
	close(fd);
	pthread_join(thread, NULL);
	return 0;
}

Linux output:

1: should lock: 0
1: should lock as EX even though locked: 0
2: should not lock: -1
1: should unlock: 0
2: should lock: 0

NuttX output (didn't lock before the change):

1: should lock: 0
1: should lock as EX even though locked: 0
2: should not lock: -1
1: should unlock: 0
2: should lock: 0

Testing first commit (behavior fix) on separate FDs within one thread:

#include <fcntl.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

static const char *name = "/tmp/test.txt";

int main(int argc, char *argv[]) {
	const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
	int fd = open(name, O_RDWR | O_CREAT, mode);
	int fd2 = open(name, O_RDWR | O_CREAT, mode);
	int ret = flock(fd, LOCK_SH);
	printf("1: should lock: %d\n", ret);
	ret = flock(fd2, LOCK_EX);
	printf("1: should lock as EX even though locked: %d\n", ret);

	sleep(5);
	ret = flock(fd, LOCK_UN);
	printf("1: should unlock: %d\n", ret);
	close(fd);
	return 0;
}

Linux output (blocked indefinitely)

1: should lock: 0

NuttX output (didn't block before the change)

1: should lock: 0

SHM test:

#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

static const char *name = "shm-test";

struct shared {
	int value;
};

static void *t(void *arg) {
	const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
	int fd = shm_open(name, O_RDWR | O_CREAT, mode);

	void *res = mmap(
		NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	int ret = flock(fd, LOCK_SH | LOCK_NB);
	printf("2: should not lock: %d\n", ret);
	sleep(1);
	ret = flock(fd, LOCK_EX);
	printf("2: should lock: %d\n", ret);

	close(fd);
	return NULL;
}

int main(int argc, char *argv[]) {
	const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
	int fd = shm_open(name, O_RDWR | O_CREAT, mode);

	void *res = mmap(
		NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

	int ret = flock(fd, LOCK_SH);
	printf("1: should lock: %d\n", ret);
	ret = flock(fd, LOCK_EX);
	printf("1: should lock as EX even though locked: %d\n", ret);

	pthread_t thread;
	pthread_create(&thread, NULL, t, NULL);

	sleep(5);
	ret = flock(fd, LOCK_UN);
	printf("1: should unlock: %d\n", ret);
	close(fd);
	pthread_join(thread, NULL);
	return 0;
}

Linux output

1: should lock: 0
1: should lock as EX even though locked: 0
2: should not lock: -1
1: should unlock: 0
2: should lock: 0

NuttX output (failed with EBADF errno before the change)

1: should lock: 0
1: should lock as EX even though locked: 0
2: should not lock: -1
1: should unlock: 0
2: should lock: 0

We need to use gettid instead of getpid, otherwise flocks applied
from different threads are considered as single thread lock and are
ignored (or updated).

Also fix the behavior if process opens the file multiple times
Linux/BSD manual states multiple file descriptors opened by a single
process shall be treated independently. Therefore we also need to
compare struct file pointer to determine whether the lock applies
to the same descriptor or not.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
We can apply file lock on SHM inode as well. Ensure file_lock_get_path
function passes and doesn't return EBADF errno.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
@michallenc michallenc requested a review from Donny9 as a code owner June 10, 2026 14:24
@github-actions github-actions Bot added Area: File System File System issues Size: S The size of the change in this PR is small labels Jun 10, 2026
@acassis

acassis commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

ping @jerpelea for v13

@lupyuen lupyuen merged commit e1a9b95 into apache:master Jun 11, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: File System File System issues Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants