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