Unable to debug a fork() call properly - c

int spawn( char* program, char** args) {
pid_t child_pid;
child_pid = fork();
if( child_pid!= 0) { // so this returns if the forking fails? Why would a fork fail?
return (int)child_pid;
}
else {
execvp(program, args);
return (int)child_pid;
}
}
I have the following code I am trying to debug. The problem is, when the parent calls it the child_pid value in my watchlist is some big number (bigger than zero) but the program itself does go in the else block.
I want to see how it goes in that else block buy my gdb debugger seems to stop after the child_pid returns its big number

Related

xv6 Start new process and exec user program

I'm trying to fork() a new process and exec() the the user program in newly created process.
This code works in user space. I'm not sure how to do the similar thing in kernel space. As per my debugging, seems like fork() never returns 0 in kernel space.
Additional question: How can I execute the user program from kernel space. Is it possible to do that with exec()?
int
main(int argc, char *argv[])
{
int pid = fork();
if(pid == 0){
// child
char *argv[2];
argv[0] = "echo";
argv[1] = "CHILD";
exec("/bin/echo", argv);
exit();
}
if(pid > 0) {
wait();
printf("parent");
}
else {
printf("ERROR");
}
exit();
}

Keep a parent process waiting and run linux command as many times as wanted

I have the below C code in linux (using gcc):
void doWho(void)
{
char entry[10];
int ret, i;
ret = read(0, entry, 10);
if (*entry == 'u')
{
for(i=0; i<3; i++)
{
execl("/usr/bin/who","who",NULL);
}
}
}
int main(int argc, char *argv[])
{
int childpid;
printf("Before it forks\n");
childpid = fork();
if(childpid == 0)
{
printf("This is a child process\n");
doWho();
exit(0);
} else
{
printf("This is the parent process\n");
wait(NULL);
}
return 0;
}
I want the parent process to keep waiting indefinitely and run "who" every time I press the "u" key. I only get the desired effect one time and then the child and parent processes exit. Any help on this?
Observe below loop :
for(i=0; i<3; i++)
{
execl("/usr/bin/who","who",NULL);
}
It doesn't matter how many times you rotate the loop , it will execute only once because when child process starts running(PCB created), you are calling function doWho then control will come to doWho function and in doWho function what you are doing ? execl(). what execl() does is that " it replaces current process(child) with new process, after when i = 0 whole child process image got replaced with new one using execl(), so there is nothing left in child process that's why it will execute only once.
If you want to execute as many as you should use fork() in the function because then exec will replace every process created by fork(), but it's not advised to run fork() in loop because your program may crash when there are no more resource available.
So replace your doWho function as
void doWho(void)
{
char entry[10] = {0};
int ret, i;
for(; ;) {
/** who command will be executed when ever condition is true **/
ret = read(0, entry, 10);
__fpurge(stdin);//to clear stdin buffer everytime
if (*entry == 'u') {
if(fork()==0)//only this newly created process will be replaces by execl not one was in main()
execl("/usr/bin/who","who",NULL);
else
;// this parents does nothing
}
}
}
I hope it helps.

C run concurrent processes, then kill them

I'm working on a program that spawns multiple processes via fork() and runs them concurrently. What I want is for the first process that ends to trigger a kill of all the other processes created. I'm getting stuck trying to figure out how to do this. I'm hoping for some suggestions. Here's what I'm thinking so far.
void done(int childid) {
kill(something?,SIGKILL);
printf("process %d signaling\n",childid);
}
int main(int argc, char **argv) {
Signal(SIGCHLD, done);
pid_t pid;
for (each command in an array) {
if ((pid = fork()) == 0) {
setpgid(0,0);
Execve(command stuff);
}
else if (pid > 0) {
printf("starting process %d\n",pid);
}
}
}
Obviously this is rather sudo-coded, but the weird thing is that the ids I get back don't match the ones that started, and obviously the parent program ends before any of the children start returning. I'm just having a very hard time with the logic here. Any help would be greatly appreciated.

returning error when execvp does not find program

int spawn( char* program, char** args) {
pid_t child_pid;
child_pid = fork();
if( child_pid > 0) { /
wait(NULL);
return (int)child_pid;
}
else {
if(execvp(program, args) == -1){
exit(EXIT_FAILURE);
}
return (int)child_pid;
}
}
I know this code is kind of messy but please bear with me: I'm trying to create my own shell. This is the function that will spin up a new child process and execute the code. However, I am unable to return an error when I type in a string.
For example, if I type 'heyman' I just get 'heyman' back while I'd like to get some sort of error ('heyman' is not a command) back.
I was hoping the exit(EXIT_FAILURE) would do that but it has not. Would appreciate if anyone could help me here
Use perror() to report the error.
if (execvp(program, args) == -1) {
perror("execvp");
exit(EXIT_FAILURE);
}
There's no need to use return (int)child_pid in the child function. If execvp() succeeds, none of the code after it runs; if it fails, you report the error and exit.

Recursive Fibonacci using Fork in C (Pt 2)

I'm attempting to write a function that recursively computes the resulting fibonacci number from a given int n using forks in C.
Here is the function specification: If doPrint is true, print it. Otherwise, provide it to the parent process. The solution should be recursive and it must fork a new child for each call. Each process should call doFib() exactly once. The method signature cannot be changed. Helper functions cannot be used.
This is a continuation of this question: Recursive Fibonacci using Fork (in C)
Unfortunately, I never figured out a solution to the problem in the last post, however this is my modified code. I thought I had it figured out (psuedo code wise) but came to find out that I still am unsure about a few pieces.
At this point, this is solely for my amusement. This is not homework and won't be covered in my class again (after the most recent test, which has passed).
static pid_t root_pid;
// Function to return exit code for PID
static int exitcode(pid_t pid)
{
pid_t retpid;
int status;
retpid = waitpid(pid, &status, 0);
if (pid != retpid)
{
printf("waitpid error\n");
}
return WEXITSTATUS(status);
}
static void doFib(int n, int doPrint)
{
root_pid = getpid();
pid_t pid1;
int status1;
pid_t pid2;
int status2;
if(n < 2) // Base case, exit back to parent?
{
exit(n);
}
else // if not base case, fork child processes
{
pid1 = fork();
if (pid1 == 0) // Child Process 1 (for fib(n-1))
{
doFib(n-1, doPrint);
exit(n-1);
}
else if (pid1 > 0) // Parent Process
{
pid2 = fork();
if (pid2 == 0) // Child Process 2 (for fib(n-2))
{
doFib(n-2, doPrint);
exit(n-2);
}
// Get value from child process 1
status1 = exitcode(pid1);
// Get value from child process 2
status2 = exitcode(pid2);
// When to print?
if (getpid() == root_pid)
{
int result = status1 + status2;
if (doPrint)
{
printf("%d\n", result);
}
else
{
exit(result);
}
}
}
}
}
A few questions...
Do I need to call both of these functions for each child process?
doFib(n-1, doPrint); exit(n-1);
Is my base case at the beginning correct? (n < 2)
Is my base case at the end correct? (when to print)
Thank you for any help.
The answer for "when to print" really comes down to what you want to print ... if you only want to print the final answer, then you'll most likely need a flag that indicates when you're in the root parent process, and use the if statement to test if you are indeed the root parent so that you only print a single number. If on the other-hand you want to print the entire sequence up to the final number, then an if statement is not needed.
For instance, a good flag value would be the PID of the root process. You could save this in a global variable called root_pid in the first couple lines of main() before you start your forking off of separate child processes. That way all the child processes will have the same value set for root_pid, and the if statement can simply be if (getpid() == root_pid).
So do something like this:
//fib.c
#include <unistd.h>
pid_t root_pid
int main()
{
root_pid = getpid();
//... rest of your program
}
And as mentioned above, make your if statement inside of doFib the following:
if (getpid() == root_pid)
{
//...print results
}
else
{
exit(result)
}

Resources