how to reopen the stdout file after closing all the descriptors? - c

I am having a problem in daemonize program. The problem is after closing all the opened descriptors, i need to reopen the stdout file to print the message.
I am having one way. But that is not working.
The way is duplicate the stdout descriptor using dup and reopen that. But the deamonize function is called it closes all the file descriptors. So, that duplicate file descriptor is also closed.
Can anyone please help me to do that.

If you use daemon() to daemonize, you can specify noclose to prevent these filedescriptors from being closed:
daemon(0, 1);
But you should close these after your check by hand, otherwise your terminals might get messed up.

Related

Closing and reopening piped file descriptors for writing in c

I have a question please regarding what happens if I closed a file descriptor after writing into it ( e.g fd[1] after piping fd ), then opened it again to write. Will the data be overwritten and all the previous ones will be gone or it will keep on writing from the end point it stopped at after the first write?
I used the system call open() with the file descriptor and no other arguments.
If you close either of the file descriptors for a pipe, it can never be reopened. There is no name by which to reopen it. Even with /dev/fd file systems, once you close the file descriptor, the corresponding entry in the file system is removed — you're snookered.
Don't close a pipe if you might need to use it again.
Consider whether to make a duplicate of the pipe before closing; you can then either use the duplicate directly or duplicate the duplicate back to the original (pipe) file descriptor, but that's cheating; you didn't actually close all the references to the pipe's file descriptor. (Note that the process(es) at the other end of the pipe won't get an EOF indication because of the close — there's still an open file descriptor referring to the pipe.)

Reopening stdin, stdout or stderr in c

I've seen this Question.
It says that we could make a copy of both the file descriptors of stdin and stdout, in order for us to reopen them at a later stage in the program.
My questions:
Could we open the file "/dev/tty" in O_WRONLY mode in order to reopen stdout?
Is this the correct method of doing it?
Is there any similar method to reopen stdin and stderr??
No, the method you posit is not the correct method. The /dev/tty "device" is your terminal device and it doesn't necessarily hold that that's where your standard output is going.
For example, if you run your program as:
yourprog >output.txt
then opening /dev/tty will not get you your starting standard output (which is the output.txt file).

Why should one redirect STDIN, STDOUT, STDERR to /dev/null, during startup of daemon?

I have seen in SO how to redirect STDIN, STDOUT, STDERR to /dev/null in C .
This is done during startup of a daemon. But, why is this necessary for a proper startup of a unix/linux daemon?
Bonus Question :
What happens if STDOUT is closed and file descriptor is used without re-opening ?
stdin, stdout and stderr are closed so that the daemon can detach successfully from the tty it was started from and also so that the daemon (or its child processes) won't write to the tty when its running.
If you attempt to read/write from a closed file descriptor, the operation will fail and errno will be set to EBADF ("fildes is not a valid file or socket descriptor open for reading"). Other than that, nothing untoward will happen.
TL;DR
You shouldn't. It is not necessary for a proper startup of a unix/linux daemon. Always write your log messages to stderr.
Bonus
errno is set to EBADF if a closed file descriptor is used, and the operation will fail.
Summary
Don't daemonize your program inside itself. Use a daemon manager to daemonize it. (Remember? Do one thing and do it right.)
Whatever program you write, always log to stderr. Doing so has the following advantages, and I quote Jonathan de Boyne Pollard:
The logging output from your dæmon will as a consequence automatically be entirely separate from the logging output of other dæmons.
You won't need any extra files in the chroot() jail at all.
Log data will not be lost and will be recorded in the same order that they were generated.
Other programs/people will not be able to insert spoof messages into the output.
Redirecting stderr to /dev/null will make it a lot harder for sysadmin to aggregate your log into their systems. You may enrage them by doing the following, I quote Chris Jester Yang:
Insist on using syslog, and don't provide any options to log to standard error or standard output.
Just to be sure, explicitly close file descriptors 1 and 2, or redirect them to /dev/null.
Reference
Mistakes to avoid when designing Unix dæmon programs
http://cloud9.hedgee.com./scribbles/daemon#logging

Redirecting stdout to socket

I am trying to redirect stdout to a socket. I do something like this:
dup2(new_fd, STDOUT_FILENO);
After doing so all stdio functions writing to the stdout fail. I have tried to reopen stdout this way:
fclose(stdout);
stdout = fdopen(STDOUT_FILENO, "wb");
But printf and other functions still don't work.
EDIT:
I am affraid that I misunderstood the problem at the first place. After some more debugging I've figured out that this is a real issue:
printf("Test"); // We get Broken pipe here
// Reconnect new_fd
dup2(new_fd, STDERR_FILENO);
printf("Test"); // This also returns Broken pipe despite that stdout is fine now
Thanks.
1: on dup2(src, dst)
A number of operating systems track open files through the use of file descriptors. dup2 internally duplicates a file descriptor from the src to dst, closing dst if its already open.
What your first statement is doing is making every write to STDOUT_FILENO to go to the object represented by new_fd. I say object because it could be a socket as well as a file.
I don't see anything wrong with your first line of code, but I don't know how new_fd is defined.
2: on reopening stdout
When you close a file descriptor, the OS removes it from its table. However, when you open a file descriptor, the OS sets the smallest available file descriptor as the returned value. Thus, to reopen stdout, all you need to do is reopen the device. I believe the device changes depending on the OS. For example, on my Mac the device is /dev/tty.
Therefore, to reopen the stdout, you want to do the following:
close(1);
open("/dev/tty", O_WRONLY);
I've solved the problem by clearing a stdio's error indicator after fixing stdout:
clearerr(stdout);
Thanks for your help.

How to re-open a closed file descriptor

I have a scenario where i created pipe for communication between two child and parent. Parent writes (using write function)data to the pipe and closes the respective file descriptor. The problem is when i want to write data again to the pipe, the write function is returning error code -1. I think its because writing end has been closed in previous iteration. Then how to open the corresponding file descriptor after it has been closed once.
I tried using open() function which requires path to some file as arguement. But i am not using any files in my application. I have simple file descriptors (int arr[2]).
Is it possible to achieve above scenario with pipes????
Once a pipe is closed, it's closed. You can't bring it back.
If you want to write more to it, don't close it in the first place - it's as simple as that.
Thing to know about anything related to files (pipes are also some sort of files) under unix: file name is used only on opening file. Later until file is open, it is available forever until closed and name is never used again. When someone deletes file in another window while it is open, just name is gone, not file. This means:
File is still on disk
It has no name
It is still open
When it is closed, kernel removes it forever
Knowing this maybe helps to understand, why this would be nearly impossible to "reopen" file, pipe or anything similar again. File name and descriptor have different lifetimes.
The only exceptions are stdout and stderr whose descriptor are always known as 1 and 2.

Resources