'Why the printf( ) is working strangely after reopening stdout stream

After reopening STDOUT stream, the message does not display on my screen if calling print() like this:

printf("The message disappeared\n")

The snippet code for explaining the problem:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>

int main(void)
{
    printf("Display a message\n");
    int fd, fd_copy, new_fd;
    FILE *old_stream = stdout;

    fd = STDOUT_FILENO;

    fd_copy = dup(fd);
    fclose(old_stream);
    new_fd = dup2(fd_copy, fd);
    close(fd_copy);
    FILE *new_stream = fdopen(fd, "w");
    stdout = new_stream;

    printf("test %d\n", 1);
    fprintf(stdout, "test 2\n");
    int rc = printf("test 3\n");
    printf("Test 4 Why the message disappeared\n");
    printf("Error message is [%s]\n", strerror(errno));

    return 0;
}

Why only the test 4 cannot display on my screen. Don't they all use stdout as output?

Output:

# gcc main.c; ./a.out
Display a message
test 1
test 2
test 3      
Error message is [Bad file descriptor]

The code snippet above comes from the LVM2 library function.

int reopen_standard_stream(FILE **stream, const char *mode)
/* https://github.com/lvmteam/lvm2/blob/master/lib/log/log.c */

The dynamic library I designed:

I wrap up a dynamic library it includes the LVM dynamic library for other processes uses. One of the functions is this (output all PVs in the system):

char global_buffer[0x1000];
void show_pvs_clbk_fn(int level, const char *file, int line,
    int dm_errno, const char *format)
{
    /* Extract and process output here rather than printing it */
    if (level != LVM2_LOG_PRINT)
        return;
    sprintf(global_buffer, "%s%s\n", global_buffer, format)
}

int show_all_PV(char *out_buffer)
{
    void *handle = lvm2_init();
    lvm2_log_fn(show_pvs_clbk_fn);
    int rc = lvm2_run(handle, "pvs");
    lvm2_exit(handle);
    if (rc != LVM2_COMMAND_SUCCEEDED) {
        return -1;
    }

    strcpy(out_buffer, global_buffer)
    return 0;
}

A caller may calls show_all_PV() API like this:

 int main(void)
 {
    char tmp[0x1000];
    if (!show_all_PV(tmp)) {
        printf("====== PVS are ======\n");
        printf("%s\n", tmp);
    }
 }

Output:

====== PVS are ======
 PV             VG   Fmt  Attr PSize  PFree
 /dev/nvme1n1p1 vg1  lvm2 a--  <1.2t   1.1t

Some caller maybe mess up the stdout:

I found a stranger thing is that if the caller defines a function which includes vfprintf(stdout, ) system call. they never get output from normal print() API.

#inclide <stdlin.h>
#inclide <stdio.h>
#inclide <unistd.h>
#inclide <stdarg.h>

#if 1
int a_function_never_be_called(const char *formatP, ...)
{
    va_list  ap;
    va_start(ap, formatP);
    vfprintf(stdout, formatP, ap);
    va_end(ap);
    return 0;
}
#endif

int main(void)
     {
        char tmp[0x1000];
        if (!show_all_PV(tmp)) {
            printf("====== PVS are ======\n");
            printf("%s\n", tmp);
        }
     }

The string "====== PVS are ======" disappeared and the caller got an IO error Bad file descripto.

Output:

 PV             VG   Fmt  Attr PSize  PFree
 /dev/nvme1n1p1 vg1  lvm2 a--  <1.2t   1.1t


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source