cygwin 3.5.4-1: lockf() aborts on overlap and does not fail on overflow
Takashi Yano
yano@tyan0.yr32.net
Thu Oct 17 22:08:06 GMT 2024
On Thu, 17 Oct 2024 18:37:57 +0200
Christian Franke wrote:
> Takashi Yano via Cygwin wrote:
> > On Mon, 14 Oct 2024 15:36:02 +0200
> > Christian Franke wrote:
> >> Two possibly independent bugs found by 'stress-ng --lockf ...':
> >>
> >> 1) lockf() may abort the process with api_fatal() if the new range
> >> partly overlaps with two ranges previously locked by the same process.
> >>
> >> 2) lockf() prints a warning on too many locks and returns success. It
> >> should not print a warning and fail with ENOLCK instead.
> >>
> >> Testcase for both:
> >>
> >> $ uname -r
> >> 3.5.4-1.x86_64
> >>
> >> $ cat locktest.c
> >> #include <fcntl.h>
> >> #include <stdio.h>
> >> #include <unistd.h>
> >>
> >> static int lock_at(int fd, int off, int size)
> >> {
> >> if (lseek(fd, off, SEEK_SET) < 0) {
> >> perror("lseek"); return -1;
> >> }
> >> printf("\rlock %d-%d\n", off, off + size - 1); fflush(stdout);
> >> if (lockf(fd, F_LOCK, size) < 0) {
> >> perror("lock"); return -1;
> >> }
> >> return 0;
> >> }
> >>
> >> int main(int argc, char **argv)
> >> {
> >> int fd = open("locktest.tmp", O_RDWR|O_CREAT, 0666);
> >> if (fd < 0) {
> >> perror("open"); return 1;
> >> }
> >>
> >> if (argc == 1) {
> >> lock_at(fd, 0, 2);
> >> lock_at(fd, 2, 2);
> >> lock_at(fd, 1, 2);
> >> }
> >> else {
> >> for (int i = 0; i < 914; i++)
> >> if (lock_at(fd, i, 1))
> >> return 1;
> >> }
> >> printf("\rdone\n");
> >> return 0;
> >> }
> >>
> >> $ gcc -o locktest locktest.c
> >>
> >> $ ./locktest
> >> lock 0-1
> >> lock 2-3
> >> lock 1-2
> >> 1 [main] locktest 44864 C:\cygwin64\tmp\locktest.exe: \
> >> *** fatal error - NtCreateEvent(lock): 0xC0000035\
> >> Hangup
> >>
> >> $ ./locktest loop
> >> lock 0-0
> >> lock 1-1
> >> lock 2-2
> >> lock 3-3
> >> ...
> >> lock 909-909
> >> lock 910-910
> >> lock 911-911
> >> 0 [main] locktest 44865 inode_t::get_all_locks_list: \
> >> Warning, can't handle more than 910 locks per file.
> >> lock 912-912
> >> 727 [main] locktest 44865 inode_t::get_all_locks_list: \
> >> Warning, can't handle more than 910 locks per file.
> >> lock 913-913
> >> 1329 [main] locktest 44865 inode_t::get_all_locks_list: \
> >> Warning, can't handle more than 910 locks per file.
> >> done
> >>
> >> There is possibly also an off-by-one error as the 912'th lockf() prints
> >> the first warning.
> > Thanks for the report.
> > I looked into the problems, and considered how to fix them.
> >
> > Could you please try the experimental patch attached?
>
>
> Works as expected with both 'locktest.exe' and 'stress-ng --lockf ...'.
Thanks for testing!
--
Takashi Yano <yano@tyan0.yr32.net>
More information about the Cygwin
mailing list