By default, when a program creates another process, GDB continues to debug the parent process while the child process runs unimpeded. If you set a breakpoint in any code that the child then executes, the child will get a SIGTRAP signal that causes it to terminate (unless it catches the signal).
To debug a child process, you can include a call to sleep in the code that the process executes after the fork or vfork call. It may be useful to sleep only if a certain environment variable is set, or a certain file exists, so the delay doesn't occur when you don't want to run GDB on the child. While the child is sleeping, you can use the pidin utility to get its process ID and then instruct GDB to attach to that process (using a new invocation of GDB if you're also debugging the parent). From that point onwards, you can debug the child process like any other process.
If you ask to debug the child process and a vfork is followed by an exec, GDB executes the child up to the first breakpoint encountered. If there's a breakpoint set on main in your original program, the breakpoint will also be set on main for the child process. Notably, when a child process is spawned by vfork, you can't debug the child or parent until the exec call completes.
If you issue a run command to GDB after an exec call executes, the new child process restarts. To restart the parent process, use the file command with the parent executable name as its argument.
You can use the catch command to make GDB stop whenever a fork, vfork, or exec call is made. For more information about catchpoints, see the C/C++ Development User Guide.