Why isn't this if statement working? [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm forking, and executing a certain block in the child process. My problem is that my child process never gets into the if statement. Why is this?
if((x = strcmp(subargs[next_redirect], ">")) == 0)
{
pid = fork();
fprintf(stderr, "my PID is %i\n", pid);
if(pid == 0)
{
fprintf(stderr, "the name of our file is %s\n", subargs[i+1]);
fp = creat(subargs[i+1], S_IWUSR | S_IRUSR);
dup2(fp, STDOUT_FILENO);
close(fp);
//create sub-command
makesubcommand(subcommand, subargs, last_redirect + 1, i);
execvp(subcommand[0], subcommand);
}
last_redirect = i;
next_redirect = getnextredirect(subargs, i+2, subargc);
}
My output is
my PID is 11080
my PID is 0
When you fork, the child process receives a PID of 0, correct?
My problem is at if(pid == 0){}. The code in that block never executes.

Your child process is not getting to if because of wait() system call.
The system call wait() blocks the calling process until one of its child processes exits or a signal is received.wait() takes the address of an integer variable and returns the process ID of the completed process. Some flags that indicate the completion status of the child process are passed back with the integer pointer. One of the main purposes of wait() is to wait for completion of child processes.
The execution of wait() could have two possible situations.
If there are at least one child processes running when the call to wait() is made, the caller will be blocked until one of its child processes exits. At that moment, the caller resumes its execution.
If there is no child process running when the call to wait() is made, then this wait() has no effect at all. That is, it is as if no wait() is there.
So remove the wait() system call. and your program will run ok.

Check the call of execvp in your code, which may have errors. You can check the return value of wait to get the child pid or -1.

Apologies. It turns out that my problem was
fprintf(stderr, "the name of our file is %s\n", subargs[i+1]);
I was left thinking that the block was never executed because this wouldn't print anything.
it turns out that there is a problem with subargs.
I appreciate all the help.

Related

Create exactly 5 process with fork() [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
For(i=0, i<3, i++){
Fork()
}
Hello, this Code creates 5 process.
How can i create only 3 processes ?
Or how do i create only Child processes ?
Thank you
When you create a fork, both the parent and the newly created child process continue from the point of forking. So, if you have a loop running three times with fork, the parent creates three children, the first child creates two children, and so on. So, your example will result in more than five processes.
When a fork is created, you can record the pid (process ID). In the child process, the pid value of itself will be 0, while the parent process will have the child's pid stored. You can use this to control subsequent forks.
To create three processes, you can use:
pid_t pid;
pid = fork();
// this will be true only in the child process
// so, only the child creates another process, resulting in a total of
// three processes
if (pid == 0) {
fork();
}
After the first call to fork(), both the parent and the child process are executing the for-loop, so both of them execute the second call to fork, and now you have more processes than you wanted. To fix this you need to make the child do something different than the parent. You can tell which process is which by looking at the return value of fork; it returns 0 in the child and a nonzero value in the parent. So, something like this:
fflush(0); // not directly relevant but always a good idea before forking
for (int i = 0; i < 3; i++) {
if (fork() == 0) {
_exit(main_for_child(i)); // very important to use _exit, not exit
}
// control reaches this point only in the parent
}

Why does a process create a zombie if execv fails, but not if execv is successful and terminates?

So I am confused by the behavior of my C program. I am using the construct,
int pid = fork();
if (pid == 0) {
if(file_upload_script_path) {
rc = execv(file_upload_script_path, args);
if(rc == -1) {
printf("Error has occured when starting file_upload.exp!\n");
exit(0);
}
} else {
printf("Error with memory allocation!\n");
}
}
else {
printf("pid=%d\n", pid);
}
To fork the process and run a script for doing file upload. The script will by itself terminate safely, either by finishing the upload or failing.
Now, there was a problem with the script path, causing execv to fail. Here I noted the child process will terminate successfully if execv finishes, but in case it fails (r==-1) and I exit the process, it will become a zombie. Anyone knows why this happens?
Note here, I know why the child-process becomes a zombie. What I am confused about is why the process not becomes a zombie if execv works.
EDIT:
I got a question about errno and the cause of the error. The cause of the error is known. There were a problem with the build process, so the path of the script were another than expected.
However, this may happen again and I want to make sure my program does not start spawning zombies when it does. The behavoir where zombies are created in some situations and not others are very confusing.
BR
Patrik
If you don't want to create zombies, your program has to reap zombie processes no matter if they call execv or not call it or no matter if the execv call succeeds. To reap zombie processes "automagically" handle SIGCHLD signal:
void handle_sigchld(int sig) {
int saved_errno = errno;
while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
errno = saved_errno;
}
int main() {
signal(SIGCHLD, handle_sigchld);
// rest of your program....
}
Inspired (no... ripped off) from: this link.
Or maybe you want only to reap only this specified child, because later you want to call fork() and handle childs return value. Then pass the returned pid from fork() in your parent to the signal handler and wait on this pid in sigchld if needed (with some checking, ex. if the pid already finished then ignore future SIGCHLD etc...).
In this scenario, when the execv fails, the child process is killed. The fun part, I think is what happens when you call exec family of functions.
The exec family of functions replaces the current image of the process with the new image of the binary you are about to exec.
So, whatever code was will not remain - and the error in your script would cause its death.
Here, the parent needs to listen on the death of the child process using wait flavour of functions (read: waitpid).
When you say that there's problem in the script, it means that the execv actually succeeded in creating the new image; but the latter failed of its own accord.
This is what I think is happening...
If the printf of if (rc==-1) is being executed, then perhaps changing exit(0) to _exit(0) should take care of it.

Does if(fork()) create a child process? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm revising for an operating systems exam and currently trying to understand this processes question:
int main()
{
int v=0;
if(fork())
{
v++;
if(!fork())
{
fork();
v--;
}
}
}
So the question asks to
Draw a tree reflecting the parent-child hierarchy of processes created when the program above is run.
How many separate copies of the integer variable v are created? Discuss what is the value of v at the end of the program for each of the processes in the tree.
The main thing I'm having an issue with is the
if(fork())
line in the code. From looking at other stack overflows I realised that
if(fork()) = if(fork() != 0)
but I'm still having difficulty understanding whether the first if statement creates a child process? Because thats the only way that the second if statement:
(!fork())
can be executed?
This is how far I've got with my current understanding of the question.
screenshot of attempt
Hopefully the diagram is legible! I'd be really grateful for any hints or pointers with this.
Notice that if (fork()) /*etc*/ is exactly the same as
pid_t newtmp = fork();
if (newtmp != 0) /*etc*/
where newtmp is a fresh (new) variable name not occurring in your program (you could use x1, x2 etc.... provided it has no occurrence in your program), and pid_t is some integral type (probably int).
Once you rewrote your code with explicit and unique names given to result of fork you'll understand it better.
BTW, the code is poor taste. When you use fork you need to handle three cases:
the fork failed (e.g. because your system has not enough memory, or because you exceeded some limits) and gives -1
the fork succeeded in the child so gives 0
the fork succeeded in the parent, so gives the pid of the child.
But when you code if (fork()) you are forgetting -or handling incorrectly- the first case (failure). It can rarely happen.
Read carefully (and several times) the fork(2) man page. Notice that fork is difficult to understand.
Regarding limits, be aware of setrlimit(2) (and the ulimit bash builtin).
The answer is
if (fork ())
may or may determine whether a child process was created.
Go to the man page:
http://man7.org/linux/man-pages/man2/fork.2.html
We find that fork () returns three types of values:
-1 => fork() failed
0 => return value in the child process
a positive value => success and the PID of the child process.
Thus the test
if (fork ())
which is the same as
if (fork () != 0)
may succeed whether or not a child process was created. A competently written question would have said
if (fork () > 0)
Assuming everything works correctly:
int main()
{
int v=0;
if(fork()) // Creates a child process that does nothing.
{
v++;
if(!fork()) // Creates a child process that creates a child process (that then does nothing but decrement v).
{
fork();
v--;
}
}
}

Why does this code using fork() work? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I've this code that executes some code depending of if the active process is the parent or the child process in an infinite loop:
pid_t childPID;
childPID=fork();
while (1)
{
if (childPID >=0)
{
if (childPID==0)
{
[do child process stuff]
}
else
{
[do parent process stuff]
}
}
else
{
printf("\n Fork failed, quitting!!!!!\n");
return 1;
}
}
Code is simple but there's one very big thing on it for me which I don't understand how it happens although I have a guess:
If not taking into consideration that we're creating 2 processes it looks like childPid is constantly being reasigned which I don't think makes any sense.
So my guess, is that fork creates a childPid for each process, returning a 0 to the parent process and the pid to the child process, even though this syntax makes me think it should only return only one result and assign it to chilPid.
Is my guess correct or is there some other thing involved?
Thank you.
So my guess, is that fork creates a childPid for each process, returning a 0 to the parent process and the pid to the child process, even though this syntax makes me think it should only return only one result and assign it to chilPid.
Exactly that. From the fork reference manual:
RETURN VALUE:
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
so
Is my guess
Why guess if this is precisely defined in the POSIX specification?
From fork(2) linux man page:
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately
So childPID is 0 in the child process and is child's pid in parent's process
What fork does is to create a new copy of the actual process to be the child process.
The childPID=fork(); is evalueated in both processes and it returns one and only one value, the trick is that the value is different depending on which of the process is executed. On the parent process it returns the PID of the new process (child), and on the child process returns 0, if fork wasn't succesful returns -1 adn the child process is never created

Using fork() in C?

I have been asked this question for homework, and am having trouble figuring it out. If anyone can help me i would really appreciate it.
What Linux library function is like a fork(), but the parent process is terminated?
I'm fairly certain that whoever assigned you this homework is looking for the exec() family of functions, from the POSIX API header <unistd.h>, because there is nothing else that more closely resembles the sort of functionality you describe.
The exec() family of functions executes a new process and replaces the currently running process address space with the newly executed process.
From the man page:
The exec() family of functions replaces the current process image with
a new process image.
It's not exactly the same as "terminating" the parent process, but in practice it results in a similar situation where the parent process address space is erased (replaced) with the address space of the child process.
What Linux library function is like a fork(), but the parent process
is terminated?
The parent process should not terminate because , it must wait for the child processes to finish executing , after which they will be in a state called "zombie state", now it is the responsibility of the parent to clean up the leftovers of the child process. The parent process can terminate without cleaning up the child processes, but then, it is not a proper way to do it, as the exit status of the child processes should be collected and checked by the parent process.
Here is an example, to demonstrate , what i just said...
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t cpid = 1 ;
int status;
cpid = fork();
// Load a application to the child using execl() , and finish the job
printf("Parent waiting for child to terminate\n");
int wait_stat = waitpid(-1,&status,0); // Parent will hang here till all child processes finish executing..
if (wait_stat < 0)
{
perror("waitpid error");
exit(-1);
}
// WIFEXITED and WEXITSTATUS are macros to get exit status information, of the child process
if (WIFEXITED (status))
{
printf("Child of id %u cleaned up\n",wait_stat);
printf("Exit status of application = %u\n",WEXITSTATUS(status));
}
}

Resources