RFR [8055421]: (fs) bad error handling in java.base/unix/native/libnio/fs/UnixNativeDispatcher.c

Ivan Gerasimov ivan.gerasimov at oracle.com
Sat Aug 23 20:09:06 UTC 2014


On 23.08.2014 1:19, Martin Buchholz wrote:
> I worry more about the integrity of the output file than about the 
> file descriptor.
> The big risk is that there is remaining buffered output that would be 
> written using fflush, the attempt to write the buffered output fails 
> with EINTR, and the resulting file is missing its last few bytes.
>
> In the real world, fclose probably doesn't encounter EINTR very often. 
>  If this was a real-world problem, I'd expect it to be a well known 
> piece of Unix folklore.
>
I think that it's not seen often because SA_RESTART flag is set by 
default for the signal handlers on most systems, so that the write 
syscall is restarted automatically.

I tried (unsuccessfully) to reproduce the issue with the following program:

#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>

void my_sighandler(int) {
}

int main(int argc, char** argv) {
   struct sigaction sa, sa1;
   sa.sa_handler = my_sighandler;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_INTERRUPT; // no SA_RESTART

   if (sigaction(SIGINT, &sa, &sa1) == -1)
     return -1;

   while (1) {
     int res, fd = dup(STDOUT_FILENO);
     FILE* f = fdopen(fd, "a");
     setvbuf(f, NULL, _IOFBF, BUFSIZ);
     fputc('A', f);
     do {
       res = fflush(f);
     } while (res == -1 && errno == EINTR);
     fputc('\n', f);
     fclose(f); // will it fail to flush, if interrupted?
   }
   return 0;
}

And I was signaling it in a loop with
$ while true; do kill -INT $procid; done;

If it had an issue with flushing the stream in fclose, it could have 
printed more than one 'A's on one line.
But it stably prints one A on every line.

If we had a reproducible test case, we could see how to fix it.
But now I can't see how else we could break it.

Sincerely yours,
Ivan



More information about the nio-dev mailing list