Why d we need child exit after execvp? - c

I have been recently wondering why do we need to use exit after the execution of a child after performing execvp. An in depth explannation is welcome.

You do not need for the child to call exit() after execvp(), but it is often wise for you to ensure that it does so. So much so as to support giving that to novices as a rule.
When a call to execvp() or one of the other exec functions succeeds, it has the effect of replacing the currently-running process image with a new one. As a result, these functions do not return on success, and nothing that follows matters in that case. The issue, then, is entirely about what to do in the event that the exec* call fails.
If you do not exit the child in the event that an exec fails then it will continue running the code of the parent. That is rarely intended or wanted. It may do work that it was not intended to do, delay the parent (that is often wait()ing for it) by not exiting promptly, and eventually mislead the parent with an exit status that is not reflective of what actually happened.
All of that, and perhaps more, is addressed by ensuring that the control flow following an exec* call pretty quickly reaches program termination with a failure status (typically via _Exit() or _exit(); less typically via exit() or abort()). Depending on the circumstances, it may or may not be appropriate to emit a diagnostic message before exiting, or to perform some other kind of cleanup.

Related

Shared library unloading and atexit handling - what order?

I'm debugging a sort of weird issue where it looks like a thread that's killed in an atexit handler is accessing a shared library, and is segfaulting because that shared library is unloaded before the exit handler runs. I'm not sure this is actually the issue, but it's a hunch on what might be happening.
When a process terminates (main exits or exit() is called), is the atexit handler the immediate next thing to run? My mind says so, but the segfault I'm seeing seems to say otherwise.
Is there any difference (with regards to exit handling) between main returning (either end of function or with return) and calling exit() directly?
When a process terminates (main exits or exit() is called), is the atexit handler the immediate next thing to run? My mind says so, but the segfault I'm seeing seems to say otherwise.
Not necessarily, you're guaranteed that atexit handlers will run. But that's it, atexit handlers may even be called concurrently with other things. While you're using c remember that c++ may be in the same process. C++ says that atexit may be called concurrently to destructors being run for objects of static duration. This means that atexit is very dangerous and you need to ensure you're being very careful what you call.
Is there any difference (with regards to exit handling) between main returning (either end of function or with return) and calling exit() directly?
According to the documentation: No.
The safest thing to do when tearing down the house: Nothing. Just get out and let the house be torn down. Closing the drapes on the way out isn't worth the time so to speak.

Is pthread_kill() dangerous to use?

I have read that TerminateThread() in WinAPI is dangerous to use.
Is pthread_kill() in Linux also dangerous to use?
Edit: Sorry I meant pthread_kill() and not pthread_exit().
To quote Sir Humphrey Appleby, the answer is "yes, and no".
In and of itself calling pthread_exit() is not dangerous and is called implicitly when your thread exits its method. However, there are a few "gotchas" if you call it manually.
All cleanup handlers are called when this is called. So if you call this method, then access some memory that the cleanup handlers have cleaned up, you get a memory error.
Similarly, after this is called, any local and thread-local variables for the thread become invalid. So if a reference is made to them you can get a memory error.
If this has already been called for the thread (implicitly or explicitly) calling it again has an undefined behaviour, and
If this is the last thread in your process, this will cause the process to exit.
If you are careful of the above (i.e. if you are careful to not reference anything about the thread after you have called pthread_exit) then it is safe to call call manually. However, if you are using C++ instead of C I would highly recommend using the std::thread class rather than doing it manually. It is easier to read, involves less code, and ensures that you are not breaking any of the above.
For more information type "man pthread_exit" which will essentially tell you the above.
Since the question has now been changed, I will write a new answer. My answer still remains "yes and no" but the reasons have changed.
pthread_kill is somewhat dangerous in that it shares the potential timing risks that is inherent in all signal handling systems. In addition there are complexities in dealing with it, specifically you have to setup a signal handler within the thread. However one could argue that it is less dangerous than the Windows function you mention. Here is why:
The Windows function essentially stops the thread, possibly bypassing the proper cleanup. It is intended as a last resort option. pthread_kill, on the other hand, does not terminate the thread at all. It simply sends a signal to the thread that the thread can respond to.
In order for this to do something you need to have registered in the thread what signals you want it to handle. If your goal is to use pthread_kill to terminate the thread, you can use this by having your signal handler set a flag that the thread can access, and having the thread check the flag and exit when it gets set. You may be able to call pthread_exit from the signal handler (I've never tried that) but it strikes me as being a bad idea since the signal comes asynchronously, and your thread is not guaranteed to still be running. The flag option I mention solves this provided that the flag is not local to the thread, allowing the signal handler to set it even if the target thread has already exited. Of course if you are doing this, you don't really need pthread_kill at all, as you can simply have your main thread set the flag at the appropriate time.
There is another option for stopping another thread - the pthread_cancel method. This method will place a cancel request on the target thread and, if the thread has been configured to be cancellable (you generally do this in the pthread_create, but you can also do it after the fact), then the next time the thread reaches a potential cancellation point (specified by pthread_testcancel but also automatically handled by many system routines such as the IO calls), it will exit. This is also safer than what Windows does as it is not violently stopping the thread - it only stops at well defined points. But it is more work than the Windows version as you have to configure the thread properly.
The Wikipedia page for "posix threads" describes some of this (but not much), but it has a pretty good "See also" and "References" section that will give you more details.

Disable SIGPIPE signal on write(2) call in library

Question
Is it possible to disable the raising of a signal (SIGPIPE) when writing to a pipe() FD, without installing my own signal handler or disabling/masking the signal globally?
Background
I'm working on a small library that occasionally creates a pipe, and fork()s a temporary child/dummy process that waits for a message from the parent. When the child process receives the message from the parent, it dies (intentionally).
Problem
The child process, for circumstances beyond my control, runs code from another (third party) library that is prone to crashing, so I can't always be certain that the child process is alive before I write() to the pipe.
This results in me sometimes attempting to write() to the pipe with the child process' end already dead/closed, and it raises a SIGPIPE in the parent process. I'm in a library other customers will be using, so my library must be as self-contained and transparent to the calling application as possible. Installing a custom signal handler could break the customer's code.
Work so far
I've got around this issue with sockets by using setsockopt(..., MSG_NOSIGNAL), but I can't find anything functionally equivalent for pipes. I've looked at temporarily installing a signal handler to catch the SIGPIPE, but I don't see any way to limit its scope to the calling function in my library rather than the entire process (and it's not atomic).
I've also found a similar question here on SO that is asking the same thing, but unfortunately, using poll()/select() won't be atomic, and there's the remote (but possible) chance that the child process dies between my select() and write() calls.
Question (redux)
Is there any way to accomplish what I'm attempting here, or to atomically check-and-write to a pipe without triggering the behavior that will generate the SIGPIPE? Additionally, is it possible to achieve this and know if the child process crashed? Knowing if it crashed lets me build a case for the vendor that supplied the "crashy" library, and lets them know how often it's failing.
Is it possible to disable the raising of a signal (SIGPIPE) when writing to a pipe() FD [...]?
The parent process can keep its copy of the read end of the pipe open. Then there will always be a reader, even if it doesn't actually read, so the condition for a SIGPIPE will never be satisfied.
The problem with that is it's a deadlock risk. If the child dies and the parent afterward performs a blocking write that cannot be accommodated in the pipe's buffer, then you're toast. Nothing will ever read from the pipe to free up any space, and therefore the write can never complete. Avoiding this problem is one of the purposes of SIGPIPE in the first place.
You can also test whether the child is still alive before you try to write, via a waitpid() with option WNOHANG. But that introduces a race condition, because the child could die between waitpid() and the write.
However, if your writes are consistently small, and if you get sufficient feedback from the child to be confident that the pipe buffer isn't backing up, then you could combine those two to form a reasonably workable system.
After going through all the possible ways to tackle this issue, I discovered there were only two venues to tackle this problem:
Use socketpair(PF_LOCAL, SOCK_STREAM, 0, fd), in place of pipes.
Create a "sacrificial" sub-process via fork() which is allowed to crash if SIGPIPE is raised.
I went the socketpair route. I didn't want to, since it involved re-writing a fair bit of pipe logic, but it's wasn't too painful.
Thanks!
Not sure I follow: you are the parent process, i.e. you write to the pipe. You do so to send a message after a certain period. The child process interprets the message in some way, does what it has to do and exits. You also have to have it waiting, you can't get the message ready first and then spawn a child to handle it. Also just sending a signal would not do the trick as the child has to really act on the content of the message, and not just the "do it" call.
First hack which comes to mind would be that you wont close the read side of the pipe in the parent. That allows you to freely write to the pipe, while not hurting child's ability to read from it.
If this is not fine, please elaborate on the issue.

Checking if input is a valid shell command, Linux

I'm developing a simple shell for an assignment. I read a command entered by the user, tokenize it, fork(), then in the child process use execvp() to execute the command in the background.
The problem is I need to implement a history feature that records valid commands. The only way I know to check if the string the user enters is a valid command is to check if execvp() returns -1. This is a fine way to check for an invalid command, but since the call to execvp() happens in the child process and the data structure I use for my history is copied to the child on fork() rather than shared, I can't update the history using the results of the execvp() within the child (since the history structure is a copy any changes I make won't be reflected in the parent's copy of the structure).
Is there any way I can check if execvp() would return -1 without actually calling it (i.e. before or after the fork)? If I could figure out a way to do that I'd be able to verify in the parent processes whether or not execvp() will succeed and use that info to update my history data structure properly.
What you are asking for is a system call which would let you implement the classic check-before-do race condition.
In that error, a program verifies whether an action is possible and then performs the action, leaving open the possibility that some external event will happen just after the check which makes the action illegal.
So then the action fails, even though the program checked that it was possible. This often results in chaos.
You should avoid this antipattern, and the system API should help by not tempting you with system calls you would only use to get yourself into trouble. In this case, the system does the right thing; there is no such API.
The parent process must eventually retrieve the exit status of the child. That is the moment you need to update (or not) the history. If a failed execvp causes the child to exit() with a failure status code, the parent will notice the failure and can react by not adding the command line to the history.
Some notes added after a bit of reflection:
To retrieve the status code of the child process, the parent will call wait or waitpid. For synchronous execution, the parent will likely do so immediately; for asynchronous execution, the parent will do so when it receives a SIGCHLD signal. But it is imperative that the parent does this, to avoid zombie processes.
In the case of asynchronous execution, it is not possible to use this strategy to avoid putting invalid commands into the history, because asynchronous commands must be recorded in the history when they are started. For a similar reason, Posix shells also count asynchronous execution of a command as successful, even if the command is invalid.
While this exercise undoubtedly has pedagogic value (as I hope this answer demonstrates), it is actually a terrible way of doing shell history. While shell users occasionally use history to retrieve and re-execute successful commands, the history feature is much more useful to retrieve and edit an unsuccessful command. It's intensely annoying to not be able to make corrections from a history feature. (Many Android applications exhibit precisely this annoying flaw with search history: after a search which gives you undesired results, you can retrieve the incorrect search and rerun it, but not modify it. I'm glad to say that things have improved since my first Android.)

determine if a process is dead or not - by PID

I have two different way to check whether a process is still up and running:
1) using GetExitCodeProcess()
2) walking the list of processes using CreateToolhelp32Snapshot() and checking PIDs
now, in both cases I'm still getting that a process that I terminated with TerminateProcess is till alive even tho it is not.
Is there a way to positively know whether a process is still alive or dead passing the PID?
thanks!
Don't use PID for something like this. PIDs are reused and have a very narrow range, with a very high collision probability. In other words, you will find a running process but will be a different process.
A call to GetExitCodeProcess should return STILL_ACTIVE for active processes. After a call to TerminateProcess, the process will be dead, and a different value will be returned.
Another way to check if a process is alive is WaitForSingleObject. If you call this on the process handle with a timeout of 0, it will immediately return WAIT_TIMEOUT if the process is still running.
You cannot assume a low level API call functions the way it seems or how you think it should function from its name or high level description. A kernel still has things to do and often calls are just requests to the kernel and there are a multitude of things a kernel needs to do (depending on implementation) before it will actually release the PID. In this case after you issue the call you may assume the process is dead, however the kernel still has to clean up.
From MSDN :
The TerminateProcess function is use
to unconditionally cause a process to
exit. The state of global data
maintained by dynamic-link libraries
(DLLs) may be compromised if
TerminateProcess is used rather than
ExitProcess.
TerminateProcess initiates termination
and returns immediately. This stops
execution of all threads within the
process and requests cancellation of
all pending I/O. The terminated
process cannot exit until all pending
I/O has been completed or canceled.
A process cannot prevent itself from
being terminated.
Could you make use of the Process Status API? There are functions for enumerating all running processes on a system - this could help you.

Resources