Im trying to emulate shell through C program. In my program whenever I run any normal (foreground) commands it works fine. Also I have handled background process with commands ending with '&'. Now to handle this I have avoided the parent waiting for a child process.
The problem is whenever for the first time in my shell I run any background command(i.e ending in '&') then it works fine. But then after that each command(normal) doesnot terminate. I guess it waits for the previously opened process. How to rectify. Please you can ask questions so that i can make myself more clear to you. This is the snippet which is doing the above mentioned task.
child_id=fork();
if(child_id==0){
//logic fo creating command
int ret=execvp(subcomm[0],subcomm);
}
//Child will never come here if execvp executed successfully
if(proc_sate!='&'){
for(i=0;i<count_pipe+1;i++){
waitpid(0,&flag,0);
}
//something to add to make it not wait for other process in my scenario for second time
}
Here proc_state just determines whether it is background or foreground.It is just a character. count_pipe is just a variable holding number of pipes (e.g ls -l|wc|wc this contains 2 pipes). Dont worry this all is working fine.
waitpid(0, &flag, 0) waits for any child process whose process group ID is equal to that of your shell. So if you have not called setsid() after the fork() of the disconnected child process, the code above will wait for that too.
pid_t pid = fork();
if (pid == 0) { /* child process */
setsid(); /* Child creates new process group */
... /* redirections, etc */
execvp(...);
}
Related
I don't know if this is the best way but I have a random number of child processes who have beed execed and wanted to implement a way to kill them without using ctrl+c. I was thinking of keeping a set of their pids and then check that set whenever I want to kill them from the parent process.
The way I was trying to do it was something like this
set<pid_t> pids;
pid_t id = fork();
if(id == 0)
{
pids.insert(getpid());
execlp("./somewhere", "./somewhere", something.c_str(), NULL);
cout << "Didn't exec" << endl;
exit(0);
}
for(auto i : pids)
{
kill(i, something?)
}
I still don't quite know how to use the kill function or how pids work so I don't know if this will work in any way, I just did a simple project in c for college and though I could try something more complex in c++.
Anyways, the objective of this is to be able to have the parent process kill a single child process out of an undefined number of running child processes, or kill them all whenever the user writes quit
kill() on pid 0 sends the signal to all members of the calling process group:
If pid is 0, sig shall be sent to all processes (excluding an
unspecified set of system processes) whose process group ID is equal
to the process group ID of the sender, and for which the process has
permission to send a signal.
If you want to kill only certain processes (as seems to be your case) take a look to Grouping child processes with setpgid()
Very strange bug, perhaps someone will see something I'm missing.
I have a C++ program which forks off a bash shell, and then passes commands to it.
Periodically, the commands will contain nonsense and the bash process will hang. I detect this using semtimedwait, and then run a little function like this:
if (kill(*bash_pid, SIGKILL)) {
cerr << "Error sending SIGKILL to the bash process!" << endl;
exit(1);
} else {
// collect exit status
long counter = 0;
do {
pid = waitpid(*bash_pid, &status, WNOHANG);
if (pid == 0) { // status not available yet
sleep(1);
}
if(counter++ > 5){
cerr << "ERROR: Bash child process ignored SIGKILL >5 sec!" << endl;
}
} while (pid != *bash_pid && pid != -1);
if(pid == -1){
cerr << "Failed to clean up zombie bash process!" << endl;
exit(1);
}
// re-initialized bash process
*bash_pid = init_bash();
}
Assuming I understand the workings of waitpid correctly, this should first send SIGKILL to the shell, and then essentially sit in a spinlock, trying to reap the resulting process. Eventually, it succeeds and then a new bash process is started with init_bash().
At least, that's what should happen. Instead, the child process's exit status is never collected, and it continues to exist as a zombie process. In spite of this, the parent does exit the loop and manages to restart the bash process, and continues with normal execution. Eventually too many zombies are generated and the system runs out of pids.
Additionally:
Fork is called in exactly one place in the program, inside init_bash.
Checks prevent init_bash from being called except once at the program's start and after a call to the function above.
Thoughts?
Articles that I read indicate that the reason for a zombie process is that a child process does an exit however the parent never collects the child's exit.
This article provides several ways to kill a zombie process from the command line. One technique is to use other signals besides SIGKILL for instance SIGTERM.
This article has an answer which suggests SIGKILL should not be used.
One of the techniques is to kill the parent thereby also killing its child processes including any zombies. The author indicates that there appear to be child processes that just remain as zombies until the OS is restarted.
You do not mention the mechanism used to communicate the commands to the child process. However one option may be to turn the child process loose by disconnecting it from its parent similar to the way a child of a terminal process can be disconnected from the terminal session. That way the child will become its own process and if there is a problem may exit without becoming a zombie.
So I have a simple fork and exec program. It works pretty good but I want to be able to detach the process that is started, I try a fork with no wait:
if((pid = fork()) < 0)
perror("Error with Fork()");
else if(pid > 0) {
return "";
}
else {
if(execl("/bin/bash", "/bin/bash", "-c", cmddo, (char*) 0) < 0) perror("execl()");
exit(0);
}
It starts the proc fine but when my main app is closed - so is my forked proc.
How do I keep the forked process running after the main proc (that started it) closes?
Thanks :D
Various things to do if you want to start a detached/daemon process:
fork again and exit the first child (so the second child process no longer has the original process as its parent pid)
call setsid(2) to get a new session and process group
reopen stdin/stdout/stderr to dereference the controlling tty, if there was one. Or, for example, you might have inherited a pipe stdout that will be broken and give you SIGPIPE if you try to write it.
chdir to / to get away from the ancestor's current directory
Probably all you really want is to ignore SIGHUP in your fork()ed process as this is normally the one which brings the program down. That is, what you need to do is
signal(SIGHUP, SIG_IGN);
Using nohup arranges for a reader to be present which would avoid possibly writing to close pipe. To avoid this you could either arrange for standard outputs not to be available or to also ignore SIGPIPE. There are a number of signals which terminate your program when not ignore (see man signal; some signals can't be ignored) but the one which will be sent to the child is is SIGHUP.
I have managed to fork and exec a different program from within my app. I'm currently working on how to wait until the process called from exec returns a result through a pipe or stdout. However, can I have a group of processes using a single fork, or do I have to fork many times and call the same program again? Can I get a PID for each different process ? I want my app to call the same program I'm currently calling many times but with different parameters: I want a group of 8 processes of the same program running and returning results via pipes. Can someone please point me to the right direction please ? I've gone through the linux.die man pages, but they are quite spartan and cryptic in their description. Is there an ebook or pdf I can find for detailed information ? Thank you!
pid_t pID = fork();
if (pID == 0){
int proc = execl(BOLDAGENT,BOLDAGENT,"-u","2","-c","walkevo.xml",NULL);
std::cout << strerror(errno) << std::endl;
}
For example, how can I control by PID which child (according to the parameter xml file) has obtained which result (by pipe or stdout), and thus act accordingly? Do I have to encapsulate children processes in an object, and work from there, or can I group them altogether?
One Fork syscall make only one new process (one PID). You should organize some data structures (e.g. array of pids, array of parent's ends of pipes, etc), do 8 fork from main program (every child will do exec) and then wait for childs.
After each fork() it will return you a PID of child. You can store this pid and associated information like this:
#define MAX_CHILD=8
pid_t pids[MAX_CHILD];
int pipe_fd[MAX_CHILD];
for(int child=0;child<MAX_CHILD;child++) {
int pipe[2];
/* create a pipe; save one of pipe fd to the pipe_fd[child] */
int ret;
ret = fork();
if(ret) { /* parent */
/* close alien half of pipe */
pids[child] = ret; /* save the pid */
} else { /* child */
/* close alien half of pipe */
/* We are child #child, exec needed program */
exec(...);
/* here can be no more code in the child, as `exec` will not return if there is no error! */
}
}
/* there you can do a `select` to wait data from several pipes; select will give you number of fd with data waiting, you can find a pid from two arrays */
It's mind-bending at first, but you seem to grasp that, when you call fork( ):
the calling process (the "parent") is
essentially duplicated by the
operating system and the duplicate process
becomes the "child"
with a unique PID all its own;
the returned value from the fork( )
call is either: integer
0,1 meaning that the
program receiving the 0 return is the
"child"; or it is the non-zero integer PID
of that forked child; and
the new child process is entered into
the scheduling queue for execution.
The parent remains in the scheduling
queue and continues to execute as
before.
It is this ( 0 .xor. non-0 ) return from fork( ) that tells the program which role it's playing at this instant -- 0 returned, program is the child process; anything else returned, program is the parent process.
If the program playing the parent role wants many children, he has to fork( ) each one separately; there's no such thing as multiple children sharing a fork( ).
Intermediate results certainly can be sent via a pipe.
As for calling each child with different parameters, there's really nothing special to do: you can be sure that, when the child gets control, he will have (copies of) exactly the same variables as does the parent. So communicating parameters to the child is a matter of the parent's setting up variable values he wants the child to operate on; and then calling fork( ).
1 More accurately: fork( ) returns a value of type pid_t, which these days is identical to an integer on quite a few systems.
It's been a while since I've worked in C/C++, but a few points:
The Wikipedia fork-exec page provides a starting point to learn about forking and execing. Google is your friend here too.
As osgx's answer says, fork() can only give you one subprocess, so you'll have to call it 8 times to get 8 processes and then each one will have to exec the other program.
fork() returns the PID of the child process to the main process and 0 to the subprocess, so you should be able to do something like:
int pid = fork();
if (pid == 0) {
/* exec new program here */
} else {
/* continue with parent process stuff */
}
is there a way for a forked child to examine another forked child so that, if the other forked child takes more time than usual to perform its chores, the first child may perform predefined steps?
if so, sample code will be greatly appreciated.
Yes. Simply fork the process to be watched, from the process to watch it.
if (fork() == 0) {
// we are the watcher
pid_t watchee_pid = fork();
if (watchee_pid != 0) {
// wait and/or handle timeout
int status;
waitpid(watchee_pid, &status, WNOHANG);
} else {
// we're being watched. do stuff
}
} else {
// original process
}
To emphasise: There are 3 processes. The original, the watcher process (that handles timeout etc.) and the actual watched process.
To do this, you'll need to use some form of IPC, and named shared memory segments makes perfect sense here. Your first child could read a value in a named segment which the other child will set once it has completed it's work. Your first child could set a time out and once that time out expires, check for the value - if the value is not set, then do what you need to do.
The code can vary greatly depending on C or C++, you need to select which. If C++, you can use boost::interprocess for this - which has lots of examples of shared memory usage. If C, then you'll have to put this together using native calls for your OS - again this should be fairly straightforward - start at shmget()
This is some orientative code that could help you to solve the problem in a Linux environment.
pid_t pid = fork();
if (pid == -1) {
printf("fork: %s", strerror(errno));
exit(1);
} else if (pid > 0) {
/* parent process */
int i = 0;
int secs = 60; /* 60 secs for the process to finish */
while(1) {
/* check if process with pid exists */
if (exist(pid) && i > secs) {
/* do something accordingly */
}
sleep(1);
i++;
}
} else {
/* child process */
/* child logic here */
exit(0);
}
... those 60 seconds are not very strict. you could better use a timer if you want more strict timing measurement. But if your system doesn't need critical real time processing should be just fine like this.
exist(pid) refers to a function that you should have code that looks into proc/pid where pid is the process id of the child process.
Optionally, you can implement the function exist(pid) using other libraries designed to extract information from the /proc directory like procps
The only processes you can wait on are your own direct child processes - not siblings, not your parent, not grandchildren, etc. Depending on your program's needs, Matt's solution may work for you. If not, here are some other alternatives:
Forget about waiting and use another form of IPC. For robustness, it needs to be something where unexpected termination of the process you're waiting on results in your receiving an event. The best one I can think of is opening a pipe which both processes share, and giving the writing end of the pipe to the process you want to wait for (make sure no other processes keep the writing end open!). When the process holding the writing end terminates, it will be closed, and the reading end will then indicate EOF (read will block on it until the writing end is closed, then return a zero-length read).
Forget about IPC and use threads. One advantage of threads is that the atomicity of a "process" is preserved. It's impossible for individual threads to be killed or otherwise terminate outside of the control of your program, so you don't have to worry about race conditions with process ids and shared resource allocation in the system-global namespace (IPC objects, filenames, sockets, etc.). All synchronization primitives exist purely within your process's address space.