ftruncate() may fail with EISDIR if other process calls open()

Christian Franke Christian.Franke@t-online.de
Mon Apr 7 07:59:29 GMT 2025


Found because 'stress-ng --fcntl 2 --verify' reports "ftruncate failed, 
errno=21":

Testcase:

$ uname -r # also with 3.6.0-1 and 3.5.7-1
3.7.0-0.43.g779e46b5b3ee.x86_64

$ cat ftruncopen.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
   const char name[] = "file.tmp";
   unlink(name);

   pid_t pid = fork();
   if (pid == (pid_t)-1) {
     perror("fork"); return 1;
   }

   int status = 1;
   int fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0600);
   if (fd < 0) {
     fprintf(stderr, "%d: ", (int)getpid()); perror("open");
   }
   else if (!pid && ftruncate(fd, 0) < 0) {
     fprintf(stderr, "%d: ", (int)getpid()); perror("ftruncate");
   }
   else
     status = 0;

   printf("%d: exit(%d)\n", (int)getpid(), status);
   if (!pid)
     return status;
   int status2 = 0;
   wait(&status2);
   return (status || status2);
}

$ gcc -o ftruncopen ftruncopen.c

$ while ./ftruncopen; do echo retry; done
11223: exit(0)
11222: exit(0)
retry
11225: exit(0)
11224: exit(0)
retry
11227: ftruncate: Is a directory
11226: exit(0)
11227: exit(1)


Problem did not occur if
- O_TRUNC is removed, or
- unlink() is removed and the file exists, or
- it is run with 'taskset 0x1'.

-- 
Regards,
Christian



More information about the Cygwin mailing list