Lone Learner Lone Learner - 1 month ago 5
C Question

Why does write() call not display output on terminal when program is run in background via Makefile?

Here is my program

foo.c
.

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

int main()
{
int i;
printf("foo\n");
write(0, "bar\n", 4);
return 0;
}


Both
foo
and
bar
are printed on the terminal if I run the program in foreground or background.

$ gcc foo.c
$ ./a.out
foo
bar
$ ./a.out &
[1] 2081
$ foo
bar

[1]+ Done ./a.out


But when I run the program via
Makefile
, I see
bar
being printed only when the program is running in foreground. It does not get printed on the terminal when the program is running in background.

Here is how my
Makefile
looks.

fg:
gcc foo.c
./a.out
sleep 1

bg:
gcc foo.c
./a.out &
sleep 1


Here is the output.

$ make fg
gcc foo.c
./a.out
foo
bar
sleep 1
$ make bg
gcc foo.c
./a.out &
sleep 1
foo
$


Why is
bar
not printed on the terminal when the program is run in background via
Makefile
?

Answer

Your program is writing to standard input with the write() system call. It isn't guaranteed that you can do that, nor is it guaranteed that when you do, it will appear on the terminal.

Most likely, make is supplying /dev/null as the standard input, so when your program attempts to write to it, it either fails (not open for writing) or succeeds in writing to the black hole.

When I revise the code in foo.c to read:

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

int main(void)
{
    if (printf("foo\n") != 4)
        fprintf(stderr, "Failed to write 4 bytes to standard output\n");
    if (write(0, "bar\n", 4) != 4)
        fprintf(stderr, "Failed to write 4 bytes to standard input\n");
    return 0;
}

and then run it with make bg, then I get:

$ make bg
gcc foo.c
./a.out &
sleep 1
Failed to write 4 bytes to standard input
foo
$