Skip to content

Commit 607792d

Browse files
raiden00plxiaoxiang781216
authored andcommitted
fs_files.c: make sure that fs_getfilep is not interrupted when holding mutex
this fixes the issue apache#6012
1 parent 784aa52 commit 607792d

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

fs/inode/fs_files.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ void files_close_onexec(FAR struct tcb_s *tcb)
547547
int fs_getfilep(int fd, FAR struct file **filep)
548548
{
549549
FAR struct filelist *list;
550+
irqstate_t flags;
550551
int ret;
551552

552553
#ifdef CONFIG_FDCHECK
@@ -574,6 +575,27 @@ int fs_getfilep(int fd, FAR struct file **filep)
574575
return -EBADF;
575576
}
576577

578+
/* Protect this part with a critical section to make sure that we won't
579+
* interrupt the mutex lock-unclock sequence below which may lead to the
580+
* priority inversion. The case is as follows:
581+
*
582+
* We have two threads: low-priority thread A and high-priority thread B,
583+
* both threads share the same task group data.
584+
*
585+
* Thread A performs IO on files periodically. Thread B is woken up by a
586+
* high-frequency interrupts, and performs IO on files periodically.
587+
*
588+
* There is a chance that thread B wakes up exactly when thread A holds
589+
* the mutex below, and consequently the file access in thread B will be
590+
* delayed due to thread A holding the list->fl_lock mutex and execution
591+
* will be returned to a thread with lower priority.
592+
*
593+
* The correct solution to this problem is to use the read-write lock,
594+
* which is currently not supported by NuttX.
595+
*/
596+
597+
flags = enter_critical_section();
598+
577599
/* The descriptor is in a valid range to file descriptor... Get the
578600
* thread-specific file list.
579601
*/
@@ -583,6 +605,7 @@ int fs_getfilep(int fd, FAR struct file **filep)
583605
ret = nxmutex_lock(&list->fl_lock);
584606
if (ret < 0)
585607
{
608+
leave_critical_section(flags);
586609
return ret;
587610
}
588611

@@ -598,6 +621,7 @@ int fs_getfilep(int fd, FAR struct file **filep)
598621
}
599622

600623
nxmutex_unlock(&list->fl_lock);
624+
leave_critical_section(flags);
601625
return ret;
602626
}
603627

0 commit comments

Comments
 (0)