Home > Enterprise >  why does redirecting stdout to result of memfd_create() only appear to work if stdout is used before
why does redirecting stdout to result of memfd_create() only appear to work if stdout is used before

Time:10-15

I am running Ubuntu 20.04 on a 64-bit machine.

I want to redirect stdout to the descriptor obtained from memfd_create. It seems the anonymous file created with memfd_create only gets the content if stdout gets a non-empty output before dup2() used for redirection. Why??

Here is the SSCCU:

#define _GNU_SOURCE        
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    int temp_fd = memfd_create("temp", 0);
    struct stat sb;

    printf("a\n");
    dup2(temp_fd, 1);
    printf("b\n");
    fstat(temp_fd, &sb);
    fprintf(stderr, "%lu\n", sb.st_size);
}

Here, 2 is printed, as expected, as the b\n gets to the anonymous file.

However, if we remove printf("a\n"); then 0 is printed.

Why?

If we replace printf("a\n") with fflush(stdout) or printf("") still 0 is printed.

If we replace with printf("a"); then 3 is printed, as expected.

It seems one has to print a non-empty string to stdout before dup2.

Edit (after the answer): what is the relevance of memfd_create()? Well, without this, the output file is not anonymous and volatile, so I just checked the result by hand afterwards and everything is fine.

CodePudding user response:

It seems that your version of libc checks whether FD 1 is a terminal or not, right before the first time it prints something. If it's a terminal, it sets up line buffering, so the buffer is flushed every time a newline is printed. Otherwise, full buffering, so it's only flushed when full.

This isn't guaranteed behaviour. It's just what the version of libc installed on your computer does.

If you want to flush the buffer at any specific time you can use fflush(stdout). Or you can use setvbuf to set a specific buffer mode.

  • Related