Encapsulation of process handling creates problems - c++

My assignment requires me to encapsulate the principle of process handling.
Here's what my Process class contains:
class Process
{
public:
Process();
~Process();
pid_t getPid() const;
private:
pid_t pid_;
};
Constructor:
Process::Process()
{
this->pid_ = fork();
}
Destructor:
Process::~Process()
{
if (this->pid_ > 0)
kill(this->pid_, SIGKILL);
}
Here's the problem: after encapsulating and creating an object like such:
void example()
{
Process pro;
if (pro.pid_ == 0)
{
// Child Process
}
else if (pro.pid_ < 0)
{
// Error
}
else
{
// Parent Process
}
}
My program almost never enters the child code, but when I fork() normally (with no encapsulation) it works like a charm.
Where did I go wrong?

This sounds like a race condition. In your case the parent most of the time seems to kill the child before it does what you expected from it. Without synchronization between the two processes, any execution order is possible. If you want the child always to perform work, you have to implement some form of synchronization. A common hack (i.e. not really synchronization) is [sleep][2]()ing in the parent. Very common is [wait][2]()ing in the parent for completion of the child.

Related

Cannot kill std::thread

I have a program that I need to run a thread in. The problem is whenever I try to kill this thread from either inside the thread or outside the thread I get a "error 6 - invalid handle" error
class myclass
{
public:
static myclass* inst()
{
if (oInst == nullptr) oInst = new myclass;
return oInst;
};
void main();
void start();
void ex_stop()
{
//HANDLE Stopper = Killer.native_handle();
//TerminateThread(Stopper, 0);
}
}
private:
std::thread Killer;
}
void myclass::start()
{
Killer = std::thread(&myclass::ex_main, this);
Killer.detach();
}
void myclass::main()
{
...
if (0 == TerminateThread(Killer.native_handle(), 0))
{
char error[200];
sprintf(error, "error %i\n", GetLastError());
printf(error);
}
This is how I start the class/thread
myclass::inst()->start();
I've also tried making std::thread Killer an extern and declaring it in my .cpp and .h files, this way I can access it from outside the class, but I still get the same "error 6, invalid thread handle" error.
Can someone please tell me what's wrong with this code? Thanks
The usual way of having a worker thread set up is to put it into a loop, and on each loop check to see if a boolean atomic has been changed ... something that would look like (but this probably doesn't compile straight off; the threadMain will probably need binding)
class myThreadJob {
public:
myThreadJob():
doRun(true),
thread(threadMain)
{}
void threadMain() {
while (doRun) {...}
}
void stop() {
doRun = false;
thread.join();
}
private:
std::atomic<bool> doRun;
std::thread thread;
}
You've not said if your thread is a will do many tasks in a queue, or if it's a one off job that it's doing, but in any case if it's expected to be a long lived thread, it should check periodically that it can still run.
Because you've called detach() on your thread, your thread is no longer associated with your process. You can think of detach() as a declaration that the thread does not need anything local to the creating thread.
You are not allowed to join it; and you're expecting it to run to termination.

What happens to RAII objects after a process forks?

Under Unix / Linux, what happens to my active RAII objects upon forking? Will there be double deletions?
What is with copy construction and -assignment? How to make sure nothing bad happens?
fork(2) creates a full copy of the process, including all of its memory. Yes, destructors of automatic objects will run twice - in the parent process and in the child process, in separate virtual memory spaces. Nothing "bad" happens (unless of course, you deduct money from an account in a destructor), you just need to be aware of the fact.
Principally, it is no problem to use these functions in C++, but you have to be aware of what data is shared and how.
Consider that upon fork(), the new process gets a complete copy of the parent's memory (using copy-on-write). Memory is state, therefore
you have two independent processes that must leave a clean state behind.
Now, as long as you stay within the bounds of the memory given to you, you should not have any problem at all:
#include <iostream>
#include <unistd.h>
class Foo {
public:
Foo () { std::cout << "Foo():" << this << std::endl; }
~Foo() { std::cout << "~Foo():" << this << std::endl; }
Foo (Foo const &) {
std::cout << "Foo::Foo():" << this << std::endl;
}
Foo& operator= (Foo const &) {
std::cout << "Foo::operator=():" << this<< std::endl;
return *this;
}
};
int main () {
Foo foo;
int pid = fork();
if (pid > 0) {
// We are parent.
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
// We are the new process.
} else {
// fork() failed.
}
}
Above program will print roughly:
Foo():0xbfb8b26f
~Foo():0xbfb8b26f
~Foo():0xbfb8b26f
No copy-construction or copy-assignment happens, the OS will make bitwise copies.
The addresses are the same because they are not physical addresses, but pointers into each process' virtual memory space.
It becomes more difficult when the two instances share information, e.g. an opened file that must be flushed and closed before exiting:
#include <iostream>
#include <fstream>
int main () {
std::ofstream of ("meh");
srand(clock());
int pid = fork();
if (pid > 0) {
// We are parent.
sleep(rand()%3);
of << "parent" << std::endl;
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
// We are the new process.
sleep(rand()%3);
of << "child" << std::endl;
} else {
// fork() failed.
}
}
This may print
parent
or
child
parent
or something else.
Problem being that the two instances do not enough to coordinate their access to the same file, and you don't know the implementation details of std::ofstream.
(Possible) solutions can be found under the terms "Interprocess Communication" or "IPC", the most nearby one would be waitpid():
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork();
if (pid > 0) {
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
...
} else {
// fork() failed.
}
}
The most simple solution would be to ensure that each process only uses its own virtual memory, and nothing else.
The other solution is a Linux specific one: Ensure that the sub-process does no clean up. The operating system will make a raw, non-RAII cleanup of all acquired memory and close all open files without flushing them.
This can be useful if you are using fork() with exec() to run another process:
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork();
if (pid > 0) {
// We are parent.
int childExitStatus;
waitpid(pid, &childExitStatus, 0);
} else if (pid == 0) {
// We are the new process.
execlp("echo", "echo", "hello, exec", (char*)0);
// only here if exec failed
} else {
// fork() failed.
}
}
Another way to just exit without triggering any more destructors is the exit() function. I generally advice to not use in C++, but when forking, it has its place.
References:
http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
man pages
The currently accepted answer shows a synchronization problem which frankly has nothing to do with what problems RAII can really cause. That is, whether you use RAII or not, you will have synchronization problems between parent and child. Heck, if you run the same process in two different consoles, you have the exact same synchronization problem! (i.e. no fork() involved in your program, just your program running twice in parallel.)
To resolve synchronization problems, you may use a semaphore. See sema_open(3) and related functions. Note that a thread would generate the exact same synchronization problems. Only you can use a mutex to synchronize multiple threads and in most cases a mutex is much faster than a semaphore..
So where you do get a problem with RAII is when you use it to hold on what I call an external resource, although all external resources are not affected the same way. I have had the problem in two circumstances and I will show both here.
Do not shutdown() a socket
Say you have your own socket class. In the destructor, you do a shutdown. After all, once you are done, you can as well send a message to the other end of the socket saying you are done with the connection:
class my_socket
{
public:
my_socket(char * addr)
{
socket_ = socket(s)
...bind, connect...
}
~my_socket()
{
if(_socket != -1)
{
shutdown(socket_, SHUT_RDWR);
close(socket_);
}
}
private:
int socket_ = -1;
};
When you use this RAII class, the shutdown() function affects the socket in the parent AND the child. That means both, the parent and the child cannot read nor write to that socket anymore. Here I suppose that the child does not use the socket at all (and thus I have absolutely no synchronization problems,) but when the child dies, the RAII class wakes up and the destructor gets called. At that point it shutdowns the socket which becomes unusable.
{
my_socket soc("127.0.0.1:1234");
// do something with soc in parent
...
pid_t const pid(fork());
if(pid == 0)
{
int status(0);
waitpid(pid, &status, 0);
}
else if(pid > 0)
{
// the fork() "duplicated" all memory (with copy-on-write for most)
// and duplicated all descriptors (see dup(2)) which is why
// calling 'close(s)' is perfectly safe in the child process.
// child does some work
...
// here 'soc' calls my_socket::~my_socket()
return;
}
else
{
// fork did not work
...
}
// here my_socket::~my_socket() was called in child and
// the socket was shutdown -- therefore it cannot be used
// anymore!
// do more work in parent, but cannot use 'soc'
// (which is probably not the wanted behavior!)
...
}
Avoid using socket in parent and child
Another possibility, still with a socket (although you could have the same effect with a pipe or some other mechanism used to communicate externally,) is to end up sending a "BYE" command twice. This is actually very close to being a synchronization problem, though, but in this case, that synchronization happens in the RAII object when it gets destroyed.
Say for example that you create a socket and manage it in an object. Whenever the object gets destroyed, you want to tell the other side by sending a "BYE" command:
class communicator
{
public:
communicator()
{
socket_ = socket();
...bind, connect...
}
~communicator()
{
write(socket_, "BYE\n", 4);
// shutdown(socket_); -- now we know not to do that!
close(socket_);
}
private
int socket_ = -1;
};
In this case, the other end receives the "BYE" command and closes the connection. Now the parent cannot communicate using that socket since it got closed by the other end!
This is very similar to what phresnel talks about with his ofstream example. Only, it is not an easy to fix synchronization. The order in which you write the "BYE\n" or another command to the socket won't change the fact that in the end the socket gets closed from the other side (i.e. synchronization can be achieved using an inter-process lock, whereas, that "BYE" command is similar to the shutdown() command, it stops the communication in its track!)
A Solution
For the shutdown() it was easy enough, we just do not call the function. That being said, maybe you still wanted to have the shutdown() happen in the parent, just not in the child.
There are several ways to fix the problem, one of them is to memorize the pid and use it to know whether these destructive function calls should be called or not. There is a possible fix:
class communicator
{
communicator()
: pid_(getpid())
{
socket_ = socket();
...bind, connect...
}
~communicator()
{
if(socket_ != -1)
{
if(pid_ == getpid())
{
write(socket_, "BYE\n", 4);
shutdown(socket_, SHUT_RDWR);
}
close(socket_);
}
}
private:
pid_t pid_;
int socket_;
};
Here we do the write() and shutdown() only if we are in the parent.
Notice that the child can (and is expected to) do the close() on the socket descriptor since the fork() called dup() on all the descriptors so the child has a different file descriptor to each file it holds.
Another Security Guard
Now there may be way more complicated cases where an RAII object is created way up in a parent and the child will call the destructor of that RAII object anyway. As mentioned by roemcke, calling _exit() is probably the safest thing to do (exit() works in most cases, but it can have unwanted side effects in the parent, at the same time, exit() may be required for the child to end cleanly--i.e. delete tmpfile() it created!). In other words, instead of using return, call _exit().
pid_t r(fork());
if(r == 0)
{
try
{
...child do work here...
}
catch(...)
{
// you probably want to log a message here...
}
_exit(0); // prevent stack unfolding and calls to atexit() functions
/* NOT REACHED */
}
This is anyway much safer just because you probably do not want the child to return in the "parent's code" where many other things could happen. Not just stack unfolding. (i.e. continuing a for() loop that the child is not supposed to continue...)
The _exit() function does not return, so destructors of objects defined on the stack do not get called. The try/catch is very important here because the _exit() is not going to be called if the child raises an exception, although it should call the terminate() function which also won't destroy all the heap allocated objects, it calls the terminate() function after it unfolded the stack and thus probably called all your RAII destructors... and again not what you would expect.
The difference between exit() and _exit() is that the former calls you atexit() functions. You relatively rarely need to do that in the child or the parent. At least, I never had any strange side effect. However, some libraries do make use of the atexit() without consideration of the possibility a fork() gets called. One way to protect yourself in an atexit() function is to record the PID of the process which requires the atexit() function. If when the function gets called the PID doesn't match, then you just return and do nothing else.
pid_t cleanup_pid = -1;
void cleanup()
{
if(cleanup_pid != getpid())
{
return;
}
... do your clean up here ...
}
void some_function_requiring_cleanup()
{
if(cleanup_pid != getpid())
{
cleanup_pid = getpid();
atexit(cleanup);
}
... do work requiring cleanup ...
}
Obviously, the number of libraries that use atexit() and do it right is probably very close to 0. So... you should avoid such libraries.
Remember that if you call execve() or _exit(), the cleanup will not occur. So in case of a tmpfile() call in the child + _exit(), that temporary file will not get deleted automatically...
Unless you know what you are doing, the child process should always call _exit() after it has done its stuff:
pid_t pid = fork()
if (pid == 0)
{
do_some_stuff(); // Make sure this doesn't throw anything
_exit(0);
}
The underscore is important. Do not call exit() in child process, it flushes stream buffers to disk (or wherever the filedescriptor is pointing), and you will end up with things written twice.

Correct Clean-Up of Parent and Children with Callbacks (C++)

This design problem pops up again and again and I still don't have a nice solution for it. It might turn out to be a design pattern ;) Only, it seems to be very C++ specific (lack of garbage collection). Anyhow, here's the problem:
We have a parent object that keeps references to child objects. The parent's state depends on (some aggregate of) its children's states. In order to be notified of state changes in its children, it passes them a reference to itself. (In another variation it passes them a callback that the children can invoke to notify the parent. This callback is a closure that keeps a reference to the parent.) The application is heavily multi-threaded. Now, this setup is a whole hornet's nest of potential race conditions and dead locks. To understand why, here's a naive implementation:
class Parent {
public:
Parent() {
children_["apple"].reset(new Child("apple", this));
children_["peach"].reset(new Child("peach", this));
}
~Parent() {
}
void ChildDone(const string& child) {
cout << "Child is DONE: " << child << endl;
}
private:
map<string, linked_ptr<Child> > children;
};
class Child {
public:
Child(const string& name, Parent* parent)
: name_(name), parent_(parent), done_(false) {}
Foo(int guess) {
if (guess == 42) done_ = true;
parent->ChildDone(name_);
}
private:
const string name_;
Parent* parent_;
bool done_;
};
Potential issues:
During destruction of the parent, it must be on the lookout for ongoing callbacks from its children. Especially if those callbacks are fired off in a separate thread. If it is not, it might be gone by the time the callback is invoked.
If there are locks in both the parent and the children (very likely in a multi-threaded non-trivial application), locking order becomes an issue: the parent invokes a method on the child, which in turn experiences a state transition and tries to notify the parent: dead-lock.
Adding/Removing children outside the constructor can be an issue if the child tries to notify the parent from its destructor. The parent must be holding a lock in order to modify the map of children, yet the child is attempting a callback on the parent.
I only scratched the surface, but one can think of other potential issues.
What I'm looking for is some advice on how to handle clean destruction of the parent in the face of threads, locks, and dynamic addition/removal of children. If anybody has come up with an elegant solution that is robust under multi-threaded deployment, please share. The keyword here is robust: it's easy to design a structure that comes with some huge caveats (child never calls parent, parent never calls child, no separate thread for callbacks, etc.), the challenge is to put as few restrictions on the programmer as possible.
Often a big part of the problem with multithreading is the failure to properly separate processing (the worker thread i.e. Child) and state.
Locking should be done via thread safe data structures not the threads themselves.
Message queues, state machines and other such tools are intended to allow you to manage such data in a controlled way that is independent of the processes used to update them.
You can almost always rework such a lifetime management problem so that it becomes a (thread safe) data management problem. The parent can be thought of as the owner of the state and the all threads update the state itself.
Reference counting to manage lifetime of objects is a common paradigm also.
If there are locks in both the parent
and the children (very likely in a
multi-threaded non-trivial
application), locking order becomes an
issue: the parent invokes a method on
the child, which in turn experiences a
state transition and tries to notify
the parent: dead-lock.
It's not clear to me why notifying the parent would cause a deadlock unless
the parent lock is held in thread A
thread A is waiting for the child to return a signal via some means
the child is signalling the parent in thread B
the parent when it receives the signal from the child in (3) attempts to obtain its lock
That's a lot of ifs. And it's a naturally problematic design: one thread (A) is holding a lock, and waiting for another thread (B) to do something.
There's no magic solution to avoid this problem - you just have to avoid it. The best answer is probably to not signal back to the parent from a separate thread; or, to distinguish between signals which will or will not be called with the parent lock already held.
During destruction of the parent, it
must be on the lookout for ongoing
callbacks from its children.
Especially if those callbacks are
fired off in a separate thread. If it
is not, it might be gone by the time
the callback is invoked.
The trick here is probably that the children should have a method (perhaps the destructor) which gaurentees that, after it returns, the child will make no further callbacks. When the parent is being destroyed it calls that method for each of its children.
I know you asked for "as few restrictions as possible" but realistically, when working in a multi-threaded environment, you have to have rules to prevent deadlocks and races.
Set a flag to notify the ChildDone function that the object is being deleted and wait for any running client thread to finish before returning from the destructor. This ensures that the object does not become invalid when a thread is executing ChildDone and no further calls to that function is accepted once the destructor is called. (Also see Should destructors be threadsafe?).
// Pseudocode, not compilable C++.
class Parent {
// ....
~Parent() {
mutex_.acquire();
shuttingDown_ = true;
mutex_.release();
foreach (Child child in children_)
child->detachParent();
waitForRunningClientThreadToExit();
}
void ChildDone(const string& child) {
mutex_.acquire();
if (!shuttingDown_)
cout << "Child is DONE: " << child << endl;
mutex_.release();
}
bool volatile shuttingDown_ = false;
Mutex mutex_;
// ....
};
class Child {
// ...
Foo(int guess) {
if (guess == 42) done_ = true;
if (parent)
parent->ChildDone(name_);
}
void detachParent() {
parent = NULL;
}
};
There's a solution with shared_ptr, enable_shared_from_this & weak_ptr trio. Take a look at your code modified:
class Parent : public std::enable_shared_from_this<Parent> {
~Parent()
{
shuttingDown = true;
}
void addChild()
{
Child c{ "some_name", weak_from_this() };
c.foo();
}
void childDone(const std::string& child)
{
if (!shuttingDown)
std::cout << "Child is DONE: " << child << std::endl;
}
std::atomic_bool shuttingDown = false;
struct Child {
std::string name;
std::weak_ptr<Parent> parent;
void foo()
{
//do smth
if (auto shared_parent = parent.lock()) {
shared_parent->childDone(name);
}
}
};
};
This code works but has one serious drawback - the parent object can't be allocated on stack, it always has to be created by making shared_ptr<Parent>. Here's a link to another question about how to get rid of that limitation.

Checking the status of a child process in C++

I have a program that uses fork() to create a child process. I have seen various examples that use wait() to wait for the child process to end before closing, but I am wondering what I can do to simply check if the file process is still running.
I basically have an infinite loop and I want to do something like:
if(child process has ended) break;
How could I go about doing this?
Use waitpid() with the WNOHANG option.
int status;
pid_t result = waitpid(ChildPID, &status, WNOHANG);
if (result == 0) {
// Child still alive
} else if (result == -1) {
// Error
} else {
// Child exited
}
You don't need to wait for a child until you get the SIGCHLD signal. If you've gotten that signal, you can call wait and see if it's the child process you're looking for. If you haven't gotten the signal, the child is still running.
Obviously, if you need to do nothing unitl the child finishes, just call wait.
EDIT: If you just want to know if the child process stopped running, then the other answers are probably better. Mine is more to do with synchronizing when a process could do several computations, without necessarily terminating.
If you have some object representing the child computation, add a method such as bool isFinished() which would return true if the child has finished. Have a private bool member in the object that represents whether the operation has finished. Finally, have another method private setFinished(bool) on the same object that your child process calls when it finishes its computation.
Now the most important thing is mutex locks. Make sure you have a per-object mutex that you lock every time you try to access any members, including inside the bool isFinished() and setFinished(bool) methods.
EDIT2: (some OO clarifications)
Since I was asked to explain how this could be done with OO, I'll give a few suggestions, although it heavily depends on the overall problem, so take this with a mound of salt. Having most of the program written in C style, with one object floating around is inconsistent.
As a simple example you could have a class called ChildComputation
class ChildComputation {
public:
//constructor
ChildComputation(/*some params to differentiate each child's computation*/) :
// populate internal members here {
}
~ChildComputation();
public:
bool isFinished() {
m_isFinished; // no need to lock mutex here, since we are not modifying data
}
void doComputation() {
// put code here for your child to execute
this->setFinished(true);
}
private:
void setFinished(bool finished) {
m_mutex.lock();
m_isFinished = finished;
m_mutex.unlock();
}
private:
// class members
mutex m_mutexLock; // replace mutex with whatever mutex you are working with
bool m_isFinished;
// other stuff needed for computation
}
Now in your main program, where you fork:
ChildComputation* myChild = new ChildComputation(/*params*/);
ChildPID= fork();
if (ChildPID == 0) {
// will do the computation and automatically set its finish flag.
myChild->doComputation();
}
else {
while (1) { // your infinite loop in the parent
// ...
// check if child completed its computation
if (myChild->isFinished()) {
break;
}
}
// at the end, make sure the child is no runnning, and dispose of the object
// when you don't need it.
wait(ChildPID);
delete myChild;
}
Hope that makes sense.
To reiterate, what I have written above is an ugly amalgamation of C and C++ (not in terms of syntax, but style/design), and is just there to give you a glimpse of synchronization with OO, in your context.
I'm posting the same answer here i posted at as this question How to check if a process is running in C++? as this is basically a duplicate. Only difference is the use case of the function.
Use kill(pid, sig) but check for the errno status. If you're running as a different user and you have no access to the process it will fail with EPERM but the process is still alive. You should be checking for ESRCH which means No such process.
If you're running a child process kill will succeed until waitpid is called that forces the clean up of any defunct processes as well.
Here's a function that returns true whether the process is still running and handles cleans up defunct processes as well.
bool IsProcessAlive(int ProcessId)
{
// Wait for child process, this should clean up defunct processes
waitpid(ProcessId, nullptr, WNOHANG);
// kill failed let's see why..
if (kill(ProcessId, 0) == -1)
{
// First of all kill may fail with EPERM if we run as a different user and we have no access, so let's make sure the errno is ESRCH (Process not found!)
if (errno != ESRCH)
{
return true;
}
return false;
}
// If kill didn't fail the process is still running
return true;
}

Linux fork within class on heap

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;
};
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.
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.
A fork will copy the heap together with the rest of the process data.