Are STDIN_FILENO and STDOUT_FILENO read only in c?
Solution 1
The constants themselves (on POSIX, STDIN_FILENO
is 0
and STDOUT_FILENO
is 1
) are indeed read-only, but the file descriptors they characterize may be closed and something else opened in their place; they're just ordinary file descriptors (usually with a flag set so that they stay open on an execve()
system call).
The thing that is changing is the table of file descriptors for the process that resides inside the OS kernel. See that syscall
instruction? That's really important here; that's the trap out of your process into the OS.
Solution 2
This is the final part of daemonizing and involves redirecting stdout
and stdin
to /dev/null
because they are not going to be used later.
Daemons normally write to log files, not to the standard output.
Citing this article:
Once it is running a daemon should not read from or write to the terminal from which it was launched. The simplest and most effective way to ensure this is to close the file descriptors corresponding to stdin, stdout and stderr. These should then be reopened, either to /dev/null, or if preferred to some other location. There are two reasons for not leaving them closed:
- to prevent code that refers to these file descriptors from failing, and
- to prevent the descriptors from being reused for some other purpose.
cpuer
Updated on June 14, 2022Comments
-
cpuer almost 2 years
fd = open("/dev/null", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } if (fd > STDERR_FILENO) { if (close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } }
man
tells me thatdup2() makes newfd be the copy of oldfd, closing newfd first if necessary.
:int dup2(int oldfd, int newfd);
But aren't
STDIN_FILENO
andSTDOUT_FILENO
read only?Dump of assembler code for function dup2: 0x00000037aa4c6ac0 <dup2+0>: mov $0x21,%eax 0x00000037aa4c6ac5 <dup2+5>: syscall 0x00000037aa4c6ac7 <dup2+7>: cmp $0xfffffffffffff001,%rax 0x00000037aa4c6acd <dup2+13>: jae 0x37aa4c6ad0 <dup2+16> 0x00000037aa4c6acf <dup2+15>: retq 0x00000037aa4c6ad0 <dup2+16>: mov 0x28a4d1(%rip),%rcx # 0x37aa750fa8 <free+3356736> 0x00000037aa4c6ad7 <dup2+23>: xor %edx,%edx 0x00000037aa4c6ad9 <dup2+25>: sub %rax,%rdx 0x00000037aa4c6adc <dup2+28>: mov %edx,%fs:(%rcx) 0x00000037aa4c6adf <dup2+31>: or $0xffffffffffffffff,%rax 0x00000037aa4c6ae3 <dup2+35>: jmp 0x37aa4c6acf <dup2+15>
Or
dup2
didn't changenewfd
at all?