michallenc opened a new pull request, #19110:
URL: https://github.com/apache/nuttx/pull/19110
## 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:
```c
#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:
```c
#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:
```c
#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
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]