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]

Reply via email to