pthread_create b/w fork and exec - c++

I wish to create a thread in a child process before the respective child process changes it's image using exec system call. However, seemingly, the pthread_create call is being overlooked.
pthread_t thread;
pthread_attr_t attribute;
pthread_attr_init(&attribute);
pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_DETACHED);
pid_t cid = fork();
if(cid == 0) //CHILD Process
{
switch(x->option)
{
case 1: pthread_create(&thread, &attribute, compressShow, NULL);
execl("/home/aamir/Lab/ass3/compression", "compression", source, destination, NULL);
cout<<"Execution failed."<<endl; break; //This segment will execute if exec fails.
}
else //PARENT Process
{
wait(0); //Prevents termination of original main until forked exec completes execution
pthread_cancel(thread);
}
The thread is basically just a progress display that is intended to output '.' (dots) in concurrence with the forked child.
If I remove the exec call the thread does execute. I've searched on google and read somewhere that you cannot use pthread_create between a fork and exec, something to do with async safe functions. Can you please help?

The exec bit zapps everything including threads and just starts a new process. That includes memory etc.
The program might (and usually) does not get to the bit to fire up the thread.

Related

Input command with system() and sleep()

Is there a way to use system() and ask for the code to wait a few seconds?
I have been trying something like:
system("MyCmd");
sleep(8000);
However, sleep() terminates "MyCmd" execution.
Any thoughts?
However, sleep() terminates "MyCmd" execution.
No. The sleep() expression doesn't terminate the child process created with the system() call, the expressions
system("MyCmd");
sleep(8000);
will just be executed sequentially.
What you can do is to call fork() to create a child process, call sleep() in the parent process, and kill() the child process, if it's still running after the parent process awakes:
pid_t pid = fork();
if (pid == 0) {
// child process
execl ("/bin/MyCmd", "MyCmd", (char *)0);
}
else if (pid > 0) {
// parent process
sleep(8000);
kill(pid,SIGKILL);
}
else {
// fork failed
printf("fork() failed!\n");
return 1;
}

Create independent process in Linux

I'm looking to implement a function similar to CreateProcess but on Linux. I did a lot of research and found the "Fork off and die" approach which uses a double fork to run the child under init. That is, allow the child to operate independent of the parent.
Because the parent needs to return information about the newly created child process (i.e. pid, name, etc.) I need to know if I'm running into a race condition in my code. Currently, I fork and retrieve the second fork's pid via pipes then wait for the first fork to exit.
int child = 0;
int fd[2] = { 0, 0 };
if (pipe (fd) != 0)
return Process();
int pid = fork();
if (pid < 0)
return Process();
if (pid == 0) // Child
{
if (setsid() != -1)
{
child = fork();
if (child == 0)
{
umask (0); // Reset umask
close (0); // Close stdin
close (1); // Close stdout
close (2); // Close stderr
execvp ( ... );
_exit (0);
}
// Do I need waitpid (child) here?
}
// Write the child PID using the pipe
write (fd[1], &child, sizeof (child));
_exit (0);
}
else // Parent
{
// Read the child PID using the pipe
read (fd[0], &child, sizeof (child));
// Remove zombie process
waitpid (pid, nullptr, 0);
// Child must finish exec by this point
return Process (child);
// Also gets name
}
Questions:
Do I need a second waitpid to wait for the child to finish the exec?
Does waitpid return upon a call to exec?
Does waitpid return even if exit or exec were called before waitpid?
You do not need to waitpid() on the second child. When a process's parent dies, the child will be adopted by the init process, so there will not be a zombie process.
waitpid() only returns after the child it waits on exits. A call to execvp() in the child means the waiter waits until the program that was executed dies, since that is when the child would die.
waitpid() will get the exit status of the process. It doesn't matter when the process actually exited.
(A little clarification: what you're calling child, is actually your grandchild. It's the child of the process that just forked off and died.)
Do I need a second waitpid to wait for the child to finish the exec?
You can't. It's your grandchild and you can only wait on your direct children. Additionally, because your grandchild's parent has died, your grandchild has now been reparented to init (so it's actually your ex-grandchild).
Does waitpid return upon a call to exec?
Waitpid returns when the given pid dies/exits or immediately if it's already a zombie. The exec is called in the grandchild. Your waitpid calls are not at all not concerned with processes that aren't your direct children (unless you're using the Linux-only child-subreaper feature).
Does waitpid return even if exit or exec were called before waitpid?
Waitpid only ever returns when the waited on pid (which must be your direct child) is dead. If that's not yet the case, it will block.

fork() 2 children with pipeline, error when wait() for both

I have the following code fork()'s 2 children from a common parent and implements a pipeline between them. When I call the wait() function in the parent once only the program runs perfectly. However if I try to call the wait() function twice (to reap from both the children), the program does nothing and must be force exited.
Can someone tell me why I can't wait for both children here?
int main()
{
int status;
int pipeline[2];
pipe(pipeline);
pid_t pid_A, pid_B;
if( !(pid_A = fork()) )
{
dup2(pipeline[1], 1);
close(pipeline[0]);
close(pipeline[1]);
execl("/bin/ls", "ls", 0);
}
if( !(pid_B = fork()) )
{
dup2(pipeline[0], 0);
close(pipeline[0]);
close(pipeline[1]);
execl("/usr/bin/wc", "wc", 0);
}
wait(&status);
wait(&status);
}
You need to close both ends of the pipe in the parent after you fork the children. The problem is that output of ls is going to the parent, and the wc is waiting for input. So the first wait cleans up the ls, but the second is waiting for wc which is blocked on a pipe that's not receiving data.
Process B (wc) does not terminate until it receives end-of-file on its input stream. The other end of the pipe is shared as both the output stream of process A, and as pipeline[1] in the parent process, so you will need to close(pipeline[1]) in the parent process before waiting for process B.

How to keep a process running?

I have a process that starts several threads which do some stuff, listen to some ports, etc.
After it starts all threads, the main thread currently goes into an infinite loop:
It's something like:
int main()
{
//start threads
while (true)
{
sleep(1000);
}
}
The extra sleep assures the main thread doesn't eat the processor.
Is this approach ok? Is there an industry standard on how a process is kept alivet? Thanks.
EDIT: Some clarifications:
the threads are listeners, so a join or WaitForSingleObject isn't an option. Usually I could use join here, but the threads are started by a third client library and I don't have any control over them.
doing some processing in the main thread doesn't make sense from a design point of view.
. Taken partially from the Linux Daemon Writing HOWTO, I assume you want something like this:
int main() {
pid_t pid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
// now start threads & do the work
for( thread *t : threads ) {
join( t );
}
return 0;
}
This way the main process will exit, child process will spawn threads which will do the work. In the end the child process will wait for those threads to finish before exiting itself.
I'd suggest you to have your main thread waiting for the termination of the others:
int main( ) {
// start threads
for( thread *t : threads ) {
join( t );
}
// finalize everything or restart the thread
return 0;
}
If you're using POSIX threads, the pthread_join function will do this.
I don't believe that there is an industry standard.
What you have is a perfectly acceptable way of running the main thread. However you may want to include a way to break out of the loop.
Other methods include:
Waiting for all the worker threads to complete using a join command.
Waiting on an event in the the main thread which can be signalled to exit the loop.
Using the main thread to do some of the processing currently done by a worker thread.
Periodically checking a boolean flag to decide whether to exit or not.
At the end of the day, it depends on your specific requirements.

Zombie process and fork

i have a code like this...
c = fork();
if(c==0) {
close(fd[READ]);
if (dup2(fd[WRITE],STDOUT_FILENO) != -1)
execlp("ssh", "ssh", host, "ls" , NULL);
_exit(1);
}
close(fd[WRITE]);
fd[READ] and fd[WRITE] are pipe file descriptors.
when i run it continuously, there are a lot of zombie processes when i use ps ax. How to rectify this? Is this because i am not using the parent to wait for the exit status of the child process...
If you have no intention to wait for your child processes, set the SIGCHLD handler to SIG_IGN to have the kernel automatically reap your children, eg.
signal(SIGCHLD, SIG_IGN);
Yes, the parent must wait for the child return status. You can do it asynchronously by catching SIGCHILD in the parent process and then call waitpid in the capture method.
Yes, waitpid() should be called from parent. waitpid() will clean-up any child process of the parent process, which is currently in terminated state.
You can add below code to your program :
if(c>0)
{
while(1){
ret = waitpid(-1,&status,0);
if(ret>0){
if(WIFEXITED(status)){
if(WEXITSTATUS(status) == 0){
printf("child process terminated normally and successfully\n");
}
else{
printf("child process terminated normally and unsuccessfully\n");
}
}
else{
printf("child process terminated abnormally and unsuccessfully\n");
}
}
if(ret<0) {
break;
}
}
}
FYI : more on waitpid.
First parameter is set to -1 such that waitpid() will clean-up any child process of this parent process, which is currently in terminated state.The first parameter can also be +ve - in this case, waitpid() will cleanup only the specific child process.Most common use is to set first parameter to -1 also refer to manual page of waitpid().
Second parameter is used to extract the termination/exit status code of the child process - waitpid() system call API fills the status field when the system call API is invoked.
Last field is the flags field - currently unused - in most cases, flags field will be set to 0 - meaning, default behaviour of the system call API !!! if you really need to use flags, refer to manual page of waitpid().
Note:
In the code you submitted, _exit(1) will be called iff execlp() fails. so you can put a condition for execlp() fail and that condition _exit() can be called. The Reason is, execlp() functions only return if an error has occurred.
Modified code can be like below :
c = fork();
if(c==0) {
close(fd[READ]);
if (dup2(fd[WRITE],STDOUT_FILENO) != -1)
ret_execlp = execlp("ssh", "ssh", host, "ls" , NULL);
if(ret_execlp == -1 ) {
printf("execlp is failed");
_exit(1);
}
}
close(fd[WRITE]);
I appreciate the above 2 answers. Wish this answer may give more clarity. Thank you.