summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--threadproc/beos/.cvsignore1
-rw-r--r--threadproc/beos/proc.c32
2 files changed, 33 insertions, 0 deletions
diff --git a/threadproc/beos/.cvsignore b/threadproc/beos/.cvsignore
index 11f54a843..f82426797 100644
--- a/threadproc/beos/.cvsignore
+++ b/threadproc/beos/.cvsignore
@@ -1,5 +1,6 @@
Makefile
apr_proc_stub
*.lo
+*.slo
.libs
.deps
diff --git a/threadproc/beos/proc.c b/threadproc/beos/proc.c
index ecbb302ca..71dd5a88f 100644
--- a/threadproc/beos/proc.c
+++ b/threadproc/beos/proc.c
@@ -149,6 +149,38 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
return errno;
}
else if (pid == 0) {
+ /* This is really ugly...
+ * The semantics of BeOS's fork() are that areas (used for shared
+ * memory) get COW'd :-( The only way we can make shared memory
+ * work across fork() is therefore to find any areas that have
+ * been created and then clone them into our address space.
+ * Thankfully only COW'd areas have the lock variable set at
+ * anything but 0, so we can use that to find the areas we need to
+ * copy. Of course what makes it even worse is that the loop through
+ * the area's will go into an infinite loop, eating memory and then
+ * eventually segfault unless we know when we reach then end of the
+ * "original" areas and stop. Why? Well, we delete the area and then
+ * add another to the end of the list...
+ */
+ area_info ai;
+ int32 cookie = 0;
+ area_id highest = 0;
+
+ while (get_next_area_info(0, &cookie, &ai) == B_OK)
+ if (ai.area > highest)
+ highest = ai.area;
+ cookie = 0;
+ while (get_next_area_info(0, &cookie, &ai) == B_OK) {
+ if (ai.area > highest)
+ break;
+ if (ai.lock > 0) {
+ area_id original = find_area(ai.name);
+ delete_area(ai.area);
+ clone_area(ai.name, &ai.address, B_CLONE_ADDRESS,
+ ai.protection, original);
+ }
+ }
+
proc->pid = pid;
proc->in = NULL;
proc->out = NULL;