Behavior different with break points on - why?

Discussion in 'Mac Programming' started by hajiman, Feb 2, 2011.

  1. hajiman macrumors newbie

    Joined:
    Feb 2, 2011
    #1
    I am running XCODE on Max OS X 10.6.6 under VMWare on a PC. Generally everything works wells. I was playing with a simple program that creates a child process using the fork() system call. When I run the program with break points off everything runs as expected. However, if I set a breakpoint after line 2 (pid = fork();) executes, I get the following output and no prompt for a carriage return. It seems like the wait(NULL) doesn't wait on the child when I break after the fork(). Any clues on why this is happening?

    Output:
    I am the parent process!
    Child Complete
    I am child or parent!

    Expected output:
    I am the parent process!
    I am the child process!

    <file names in directory>

    Child Complete
    I am child or parent!


    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>

    int main()
    {
    pid_t pid;
    /* fork another process */
    pid = fork();
    if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed");
    exit(-1);
    }
    else if (pid == 0) { /* child process */
    printf ("I am the child process!\n");
    getc(stdin);
    execlp("/bin/ls", "ls", NULL);
    printf ("I am the child process again!\n");
    }
    else { /* parent process */
    printf ("I am the parent process!\n");
    /* parent will wait for the child to complete */
    wait (NULL);
    printf ("\nChild Complete\n");
    //exit(0);
    }

    printf ("I am child or parent!\n");
    }
     
  2. sammich macrumors 601

    sammich

    Joined:
    Sep 26, 2006
    Location:
    Sarcasmville.
    #2
    I remember I had this problem, and it took me a while to figure it out. My knowledge isn't in-depth enough to explain the problem but just know that I know that breakpoints break child process debugging and I had to do a lot of workaround testing.

    (I was writing a basic process kernel for a course at uni, while it was incredibly enlightening, this was probably my most annoying bug I came across in that subject).

    PS. I may have had a basic concept of the problem that was occurring but I've since forgotten what it was, but I'm certain that somehow breakpoints mess up the signals sent between the processes, or the breakpoint actually kills the child process (?).
     
  3. holmesf, Feb 2, 2011
    Last edited by a moderator: Feb 22, 2011

    holmesf macrumors 6502a

    Joined:
    Sep 30, 2001
    #3
    One very likely explanation:
    http://sourceware.org/gdb/onlinedocs/gdb/Forks.html

    So when the child hits the breakpoint, it gets sent SIGTRAP and terminates. The parent sees that the child terminates and continues executing. This is consistent with your program output.

    This one. :)
     
  4. sammich macrumors 601

    sammich

    Joined:
    Sep 26, 2006
    Location:
    Sarcasmville.
    #4
    Score 1 sammich! :D

    Maybe I should've made a thread on this bug instead of losing sleep :( But yeah I think I got around to the conclusion with a lot of fiddling and putting a print statement at the top of the program (which would get executed when it got forked).
     
  5. hajiman thread starter macrumors newbie

    Joined:
    Feb 2, 2011
    #5
    Ok, I certainly didn't expect such speedy replies. In case anyone is interested, I did a few more experiments and it looks like holmesf's link nails it right on the head. If I put a breakpoint in the else statement that only the parent executes everything runs just fine but if I put a breakpoint anywhere in the code the child executes, the child appears to get terminated even before the debugger gets near the breakpoint.

    Thanks much!
     
  6. cqexbesd macrumors regular

    Joined:
    Jun 4, 2009
    #6
    If you ever do need to debug the child process an easy way is to just get the child to pause long enough for you to attach to it with gdb in a different terminal. The quick and dirty way is to just put a sleep in the child after the fork and get the parent or the child to print or log the child's PID then "gdb a.out PID".

    Of course if you ever have real time constraints etc then this technique can be more hairy - but then that holds true for using a debugger in general.

    HTH

    Andrew
     

Share This Page