- /* It is generally good practice to flush any possible pending stdio
- output prior to doing a fork, to avoid the possibility of both
- the parent and child flushing the same data after the fork. */
- gdb_flush (gdb_stdout);
- gdb_flush (gdb_stderr);
-
- /* If there's any initialization of the target layers that must
- happen to prepare to handle the child we're about fork, do it
- now... */
- if (pre_trace_fun != NULL)
- (*pre_trace_fun) ();
-
- /* Create the child process. Since the child process is going to
- exec(3) shortly afterwards, try to reduce the overhead by
- calling vfork(2). However, if PRE_TRACE_FUN is non-null, it's
- likely that this optimization won't work since there's too much
- work to do between the vfork(2) and the exec(3). This is known
- to be the case on ttrace(2)-based HP-UX, where some handshaking
- between parent and child needs to happen between fork(2) and
- exec(2). However, since the parent is suspended in the vforked
- state, this doesn't work. Also note that the vfork(2) call might
- actually be a call to fork(2) due to the fact that autoconf will
- ``#define vfork fork'' on certain platforms. */
- if (pre_trace_fun || debug_fork)
- pid = fork ();
- else
- pid = vfork ();
-
- if (pid < 0)
- perror_with_name (("vfork"));
-
- if (pid == 0)
- {
- if (debug_fork)
- sleep (debug_fork);
-
- /* Create a new session for the inferior process, if necessary.
- It will also place the inferior in a separate process group. */
- if (create_tty_session () <= 0)
- {
- /* No session was created, but we still want to run the inferior
- in a separate process group. */
- debug_setpgrp = gdb_setpgid ();
- if (debug_setpgrp == -1)
- perror ("setpgrp failed in child");
- }
-
- /* Ask the tty subsystem to switch to the one we specified
- earlier (or to share the current terminal, if none was
- specified). */
- new_tty ();
-
- /* Changing the signal handlers for the inferior after
- a vfork can also change them for the superior, so we don't mess
- with signals here. See comments in
- initialize_signals for how we get the right signal handlers
- for the inferior. */
-
- /* "Trace me, Dr. Memory!" */
- (*traceme_fun) ();
-
- /* The call above set this process (the "child") as debuggable
- by the original gdb process (the "parent"). Since processes
- (unlike people) can have only one parent, if you are debugging
- gdb itself (and your debugger is thus _already_ the
- controller/parent for this child), code from here on out is
- undebuggable. Indeed, you probably got an error message
- saying "not parent". Sorry; you'll have to use print
- statements! */
-
- /* There is no execlpe call, so we have to set the environment
- for our child in the global variable. If we've vforked, this
- clobbers the parent, but environ is restored a few lines down
- in the parent. By the way, yes we do need to look down the
- path to find $SHELL. Rich Pixley says so, and I agree. */
- environ = env;
-
- /* If we decided above to start up with a shell, we exec the
- shell, "-c" says to interpret the next arg as a shell command
- to execute, and this command is "exec <target-program>
- <args>". */
- if (shell)
- {
- execlp (shell_file, shell_file, "-c", shell_command, (char *) 0);
-
- /* If we get here, it's an error. */
- fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
- safe_strerror (errno));
- gdb_flush (gdb_stderr);
- _exit (0177);
- }
- else
- {
- /* Otherwise, we directly exec the target program with
- execvp. */
- int i;
- char *errstring;
-
- execvp (exec_file, argv);
-
- /* If we get here, it's an error. */
- errstring = safe_strerror (errno);
- fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);
-
- i = 1;
- while (argv[i] != NULL)
- {
- if (i != 1)
- fprintf_unfiltered (gdb_stderr, " ");
- fprintf_unfiltered (gdb_stderr, "%s", argv[i]);
- i++;
- }
- fprintf_unfiltered (gdb_stderr, ".\n");
-#if 0
- /* This extra info seems to be useless. */
- fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);
-#endif
- gdb_flush (gdb_stderr);
- _exit (0177);
- }
- }
-
- /* Restore our environment in case a vforked child clob'd it. */
- environ = save_our_env;
-
- init_thread_list ();