Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is data not being flushed to file on process exit?

int main(int argc, char *argv[])
{
    FILE *fp = fopen("a.txt", "wt");

    fprintf(fp, "AAAA");

    // No flush. and No close
    raise(SIGTERM);

    exit(EXIT_SUCCESS);
}

result: No data has written to a.txt

I expected this is fine. Because the system will close the file handle and then the filesystem driver flushes the unflushed data in his Close handler. But it wasn't. I tested this code on EXT4, ubuntu 11.10

Question: I thought ALL filesystems must flush unflushed data at his close processing.
Posix doesn't have the rule?

P.S This code worked well (flushed well) on NTFS, Win7

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h = CreateFile(L"D:\\a.txt", GENERIC_READ|GENERIC_WRITE,
        0, 0, OPEN_ALWAYS, 0, 0);
    BYTE a[3];
    memset(a, 'A', 3);
    DWORD dw;
    WriteFile(h, (PVOID)a, 3, &dw, 0);

    TerminateProcess(GetCurrentProcess(), 1);
    return 0;
}

Edit:
I tested it again with system call write. And it was flushed well.

int main(int argc, char** argv)
{
    int fd = open("a.txt", O_CREAT|O_TRUNC|O_WRONLY);
    char buf[3];
    memset(buf, 'A', 3);
    size_t result = write(fd, buf, 3);

    raise(SIGTERM);
    exit(EXIT_SUCCESS);   
    return 0;
}
like image 278
Benjamin Avatar asked Sep 02 '11 08:09

Benjamin


People also ask

Does exit flush buffers?

Will buffer be automatically flushed to disk when a process exits? In general the answer is no.

Does _exit flush open streams?

Open stdio(3) streams are not flushed. On the other hand, _exit() does close open file descriptors, and this may cause an unknown delay, waiting for pending output to finish. If the delay is undesired, it may be useful to call functions like tcflush(3) before calling _exit().


2 Answers

This isn't anything to do with the filesystem, rather it's the behaviour of the C implementation you are using that determines when open streams are flushed or not.

Under POSIX, the default action action for the SIGTERM signal is:

Abnormal termination of the process. The process is terminated with all the consequences of _exit()...

_exit() is equivalent to _Exit() according to the C standard and the choice of whether to flush streams is not specified by the standard:

The _Exit() and _exit() functions shall not call functions registered with atexit() nor any registered signal handlers. Whether open streams are flushed or closed, or temporary files are removed is implementation-defined...

Assuming you are using glibc on Linux, from the documentation (emphasis mine):

When a process terminates for any reason—either because the program terminates, or as a result of a signal—the following things happen:

  • All open file descriptors in the process are closed. See Low-Level I/O. Note that streams are not flushed automatically when the process terminates; see I/O on Streams.

I'm not familiar with the Windows' WriteFile and TerminateProcess so I can't comment on what the documented behaviour is.

like image 95
TheJuice Avatar answered Oct 27 '22 07:10

TheJuice


It doesn't have anything to do with file system drivers. The issue is that the CRT is buffering the file stream itself. You set the buffer size with setvbuf(), it uses a default if you don't use this function. There's no buffering in the application when you use WriteFile(), output is buffered in the operating system's file system cache. Immune from abrupt app aborts.

You'll have to call fflush() to achieve the same.

like image 26
Hans Passant Avatar answered Oct 27 '22 05:10

Hans Passant