Thread: Problem with Fork()

  1. #1
    Registered User
    Join Date
    Apr 2003
    Posts
    23

    Problem with Fork()

    After I fork I appear to lose my variable the first time I try to execute a program. It will run the 2nd, 3rd,.... time but not the first. Below is my code.
    This is part of the shell code I am writing, so everything is in a while loop. it appears to lose the execCommand variable. For instance with I run a ps command the first time and print execCommand after the for it comes out as a ?. Every other time though it comes out ok.

    thank you.
    Code:
    childPid = fork();
          
          if (childPid < 0)
          {
            perror ("fork");
            return 0;
          }
          
          if (childPid == 0)
          {
            
            if (execlp (execCommand, execCommand,(char*)0) == -1)
              perror("exec");
    
          }
          /* Have the parent wait for child to complete */
          if (wait (&status) < 0)
            perror ("wait");

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    How exactly did you declare execCommand ?

    Whichever way you do it, either the first or the second parameter of execlp() will be wrong
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    I don't know if that's the issue.. when I print execCommand it comes up as ??'s.. it appears to lose it at the fork... anyway I delcared execCommand as a char by char * execCommand=malloc(100).

    I don't understand why it keeps losing the variables at the fork.. I didn't know that was an issue with forks.

  4. #4
    root
    Join Date
    Sep 2003
    Posts
    232
    >I didn't know that was an issue with forks.
    It isn't, but you're most likely not using execlp correctly. The first argument is the program to run, the second argument is the arguments to pass to the program. For example, if execCommand is "ls", then would you honestly expect
    Code:
    $ ls ls
    to work? Anyway, try giving us some code that compiles and shows your problem (as short as possible, please). That way we can be more helpful.
    The information given in this message is known to work on FreeBSD 4.8 STABLE.
    *The above statement is false if I was too lazy to test it.*
    Please take note that I am not a technical writer, nor do I care to become one.
    If someone finds a mistake, gleaming error or typo, do me a favor...bite me.
    Don't assume that I'm ever entirely serious or entirely joking.

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    Isn't ls ls what I want? when I hard code ls in there then it works... again the variable is losing its value before it gets there


    I just don't understand why it is losing its value ... I can get code here but I have to relogin under Linux ...

    I don't think the problem is with the execlp. execlp("ls", "ls".. works...
    Code:
    execCommand = "ls";
    fork();
    execlp(execCommand, execCommand ...
    does not work.

    furthermore...
    Code:
    execCommand = "ls";
    fork()
    printf("%s",execCommand);
    does not work it displayes ??'s for the characters...
    Last edited by Schwarzhelm; 10-31-2003 at 03:11 PM.

  6. #6
    root
    Join Date
    Sep 2003
    Posts
    232
    >Isn't ls ls what I want?
    Not exactly. Try this and see if fork does something to your variable, the following works perfectly for me:
    Code:
    Fri Oct 31 4:12:58pm
    sangut: ~/misc
    > <c.c less
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdio.h>
    
    int main ( ) {
            char *p = "ls";
    
            switch (fork()) {
            case -1:
                    perror("No forkie");
                    break;
            case 0:
                    printf("Child: %s\n", p);
                    break;
            default:
                    printf("Parent: %s\n", p);
                    break;
            }
            wait(NULL);
    
            return 0;
    }
    The information given in this message is known to work on FreeBSD 4.8 STABLE.
    *The above statement is false if I was too lazy to test it.*
    Please take note that I am not a technical writer, nor do I care to become one.
    If someone finds a mistake, gleaming error or typo, do me a favor...bite me.
    Don't assume that I'm ever entirely serious or entirely joking.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    That worked ... hmm that leaves me in a mess now.. ok it works if I define the variable directly like you did. hmm what could i be doing wrong?

    The user inputs a commad and it holds until fork. If I hardcode it works fine. Any ideas.. this is kind of hard to explain.

  8. #8
    root
    Join Date
    Sep 2003
    Posts
    232
    >Any ideas.. this is kind of hard to explain.
    Source code, something we can compile. Just give me a quick program like I posted so I can test it.
    The information given in this message is known to work on FreeBSD 4.8 STABLE.
    *The above statement is false if I was too lazy to test it.*
    Please take note that I am not a technical writer, nor do I care to become one.
    If someone finds a mistake, gleaming error or typo, do me a favor...bite me.
    Don't assume that I'm ever entirely serious or entirely joking.

  9. #9
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <fcntl.h>
    #include <time.h>
    #include <sys/param.h>
    
    char history[100][100];
    int historyCount = 1;
    char background[100][100];
    char globalCommand[100];
    
    
    
    
    int main(int argc, char *argv[])
    {
      while (1)
      {
        pid_t childPid;
        int    status;
        char * cmdLine=malloc(100);
        char * path=malloc(100);
        char * execCommand=malloc(100);
        path = printPrompt();
        printf("%s# ",path);
    
        
        cmdLine = readCommandLine();
       
        //if( isBuiltInCommand(cmdLine, path) == 1)
        {
          if (strcmp("exit", cmdLine) == 0)
          {
            exit(8);
          }
          else
            //executeBuiltInCommand(cmdLine, path);
        }
        
        else
        {
          
          execCommand = cmdLine;
          printf("%s\n", execCommand);
       
          childPid = fork();
          
          //if (childPid == 0)
          {
            //if (execlp (globalCommand, globalCommand,(char*)0) == -1)
            //    perror("exec");
            printf("%s\n",execCommand);
          }
          if (childPid < 0)
          {
            perror ("fork");
            return 0;
          }
          
          //if (childPid == 0)
          //{
    
            //if (execlp ("ps", "ps",(char*)0) == -1)
            //  perror("exec");
            //exit(127);
            //printf("childPid %i\n", childPid);
          //}
          /* Have the parent wait for child to complete */
    
          
          else
          {
            //if (runInForeground(cmdLine))
            {
            if (wait (&status) < 0)
              perror ("wait");
    
            }
            /*else
            {
              //record list of background jobs
            } */
          } 
        } 
    
      }    
             
      return EXIT_SUCCESS;
    }

  10. #10
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Some thoughts:

    >>char * cmdLine=malloc(100);
    >>cmdLine = readCommandLine();
    You're malloc()ing memory and assigning the pointer to cmdLine. Then, you call a function and gives it's return code to cmdLine as well, thus loosing the address of the malloc()'d memory. Instant memory leak, and potential problem.

    >>char * execCommand=malloc(100);
    >>execCommand = cmdLine;
    And now you've gone and done the same thing again.


    There's too much commented out code in your post. It's unclear what you're trying to do with it. It's better to clean the code before posting here, you'll get better help that way.

    As for the fork(), make sure you use a method like twm showed, with regards to the return value.

    As for your use of execlp(), the first two parameters are correct, it's perfectly valid to have them both set to the name of the program (despite what you've been told ). Here's an example taken from the POSIX site:

    Code:
    Using execlp()
    The following example searches for the location of the ls command 
    among the directories specified by the PATH environment variable.
    
    #include <unistd.h>
    
    int ret;
    ...
    ret = execlp ("ls", "ls", "-l", (char *)0);
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well, for starters you have a memory leak:
    Code:
    char * execCommand=malloc(100);
    ...
    
    else
    {
          execCommand = cmdLine;
    You've probably got two of them:
    Code:
    char * cmdLine=malloc(100);
    ...
    cmdLine = readCommandLine();
    [edit]
    Curses, Foiled again!
    [/edit]

    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    Sorry about all the commented code. I was trying to comment out all the calls to the other sub routines that I didn't post here. I also have been playing with the stuff around the fork to see if I could fix my problem. It sounds like the memory leak might be my problem. How do I declare the cmdLine value? Do I just declare it as char cmdLine[100] or is there something else I need to do to fix the memory leak?

    Thank you

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >is there something else I need to do to fix the memory leak?
    If you don't want memory leaks, don't use dynamic memory allocation. It's as simple as this (for now at least ): When you don't know the size of a string until runtime, or you expect the size of the string the change, use dynamic memory. Otherwise, don't.

    However, in this case, it depends on how readCommandLine works. Most likely it allocates memory and returns a pointer to that memory. So you would create a pointer and simply assign the return of readCommandLine to that pointer. There's no need to use malloc, but you probably need to use free later.
    My best code is written with the delete key.

  14. #14
    Registered User
    Join Date
    Apr 2003
    Posts
    23
    It still messes up... After my fork I lose the variable even when I try to print it, it prints a ?... any other suggestions?

    Here's my main again with not as much stuff commented out... It may not work for you though you may have to comment out the sub routine calls that aren't there.

    Code:
    int main(int argc, char *argv[])
    {
      while (1)
      {
        pid_t childPid;
        int    status;
        char  * cmdLine;
        char * path;
        char * execCommand;
        path = printPrompt();
        printf("%s# ",path);
    
        
        cmdLine = readCommandLine();
       
        if( isBuiltInCommand(cmdLine, path) == 1)
        {
          if (strcmp("exit", cmdLine) == 0)
          {
            exit(8);
          }
          else
            executeBuiltInCommand(cmdLine, path);
        }
        
        else
        {
          execCommand = cmdLine;
          printf("command Line: %s",cmdLine);
          printf("test %s\n", cmdLine);
       
          childPid = fork();
          printf("balls %s\n",cmdLine);
          if (childPid == 0)
          {
            if (execlp (execCommand, execCommand,(char*)0) == -1)
                perror("exec");
            
          }
          if (childPid < 0)
          {
            perror ("fork");
            return 0;
          }
          
          
          else
          {
            //if (runInForeground(cmdLine))
            {
            if (wait (&status) < 0)
              perror ("wait");
    
            }
            /*else
            {
              //record list of background jobs
            } */
          } 
        } 
    
      }    
             
      return EXIT_SUCCESS;
    }
    Thank you
    Last edited by Schwarzhelm; 11-02-2003 at 09:21 PM.

  15. #15
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Post this function: readCommandLine
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  2. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  3. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  4. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  5. Replies: 5
    Last Post: 11-07-2005, 11:34 PM