Linux fork within class on heap

2019-05-04 10:09发布

问题:

What happens when I have the following situation:

class A: holds on to dynamically allocated object B's. It will create and destroy these.

class B: has an execute function called by A. Execute will fork() and the child will use execvp to run another process. BUT, a flag can be set so that the parent will not wait for the child (allows it to run in the background).

My question is, what is fork doing in this case? I know that the child has a complete copy of the process of the parent, but I'm a little confused. So does that mean that the child process has its own object A which holds the B? And what happens if B is not waiting, but A deletes the B?

Here is some sample code. Note that it is simplified from what I am actually doing.

class B;
class A
{
    public:
    void addAction( const std::string &name )
    {
        _bq.push( new B( name ) );
    }

    void doActions( bool wait = true )
    {
        while ( !_bq.empty() )
        {
            B* b = _bq.front();
            b->execute( wait );
            _bq.pop();
            delete b;
        }
    }

    ~A() { //omitted, but just deletes everything in queue }

    private:
    std::queue<B*> _bq;
};

class B
{
    public:
    B( const std::string &name )
    {
        args.push_back( name.c_str() );
        args.push_back( NULL );
    }
    void execute( bool waitForChild )
    {
        pid_t pid = fork();
        if ( pid != 0 )
        {
            if (waitForChild)
            {
                int status;
                wait( &status );
                // check status...
             }
        }
        else
        {
            execvp( args[0], const_cast<char**>( &args[0] ) );
            // problem
            exit( 100 );
        }
    }
    private:
    std::vector<char*> args;
};

回答1:

The child process is completely separate from the parent, and has a complete copy of the parent's variables. When the child executes (calls execve() or one of its relatives), no C++ destructors are executed. However, this has no effect whatsoever on the parent process.

So, there is no interference between the child and the process. It does not matter whether the parent waits for the child or not. As soon as the fork() returns (successfully) to the parent process, the child is running independently and nothing that the parent does to allocated variables will affect the child.

If you really try hard and have shared memory and variables allocated into shared memory via placement new and if the child goes cleaning variables up in shared memory before calling execvp(), or some other similarly far-fetched but not actually impossible scenario, then the child and parent are not completely independent. However, if you were doing something as complex as that, you probably would not be asking the question, either.



回答2:

When you fork your process, you get an entire copy of the process (although typically it is implemented using copy-on-write), and by "entire copy", I mean an entire copy; including the various pages that have been allocated for that process, so logically there is a whole other copy of the heap and, for each thread, a copy of that thread and its associated stack, so yes, you have two copies of A and B.

A more pressing question, though, when it comes to forking is what happens to threads? Or what happens if you add an "atfork" hook for one of your threads? This one of the few ways that fork+exec can be fairly broken-ish or difficult to use within a UNIX context. It's usually a good idea to solve this once with a library or use popen, rather than trying to solve this multiple times all over the place.



回答3:

A fork will copy the heap together with the rest of the process data.