
I've downloaded the not-yet-Boost coroutine library [1] from the Boost Vault [2]. On a couple of Linux platforms I was able to build and run example/banana.cpp -- though I had to patch noreturn.hpp for gcc 3.3 [3]. On an Intel "fall 2008" MacBook Pro running OS X 10.5.6, with Apple gcc 4.0.1, I had to comment out the MAP_ANONYMOUS mmap() flag [4] -- I don't think that flag is available in Darwin. (Obviously that patch should test for MAP_ANONYMOUS rather than simply suppressing it.) Having done that, the 'banana' example program built -- but I get a bus error trying to run it. I did find an exchange on the Apple mailing list [5] in which Kevin Van Vechten recommends #defining _XOPEN_SOURCE before #include <ucontext.h>:
Why the bus error? What am I doing wrong?
This is a known issue where getcontext(3) is writing past the end of the ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). As a workaround, define _XOPEN_SOURCE before including ucontext.h.
Unfortunately, adding such a #define [6] does not resolve my bus error. The article [7] in which I found ref [5] proposes a classic-C program [8] to illustrate use of getcontext() and swapcontext(). On my Mac, that program produces a seg fault with or without #define _XOPEN_SOURCE. So my apologies: this may very well not be a Boost issue, or even a pre-Boost issue. I'm very excited to try the coroutine library, but crashing on Macs is a show-stopper for us. Has anyone else succeeded in running it on a Mac? [1] http://www.crystalclearsoftware.com/soc/coroutine/index.html [2] http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-c... [3] attached boost-coroutine.gcc33.patch [4] attached boost-coroutine.osx-mmap.patch [5] http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html [6] attached boost-coroutine.osx-context.patch [7] http://hjiang.net/archives/220 [8] attached swapcontext_test.c *** boost/coroutine/detail/noreturn.hpp~ Sun Aug 20 10:11:09 2006 --- boost/coroutine/detail/noreturn.hpp Fri Mar 27 17:00:00 2009 *************** *** 40,48 **** --- 40,54 ---- #if defined(__GNUC__) + #if __GNUC_MAJOR__ > 3 || (__GNUC_MAJOR__ == 3 && __GNUC_MINOR__ > 3) #define BOOST_COROUTINE_NORETURN(function) \ function __attribute__((__noreturn__)) \ /**/ + #else // gcc 3.3 + #define BOOST_COROUTINE_NORETURN(function) \ + function + /**/ + #endif // gcc 3.3 #elif defined (BOOST_MSVC) *** boost/coroutine/detail/posix_utility.hpp~ Sun Aug 20 13:11:09 2006 --- boost/coroutine/detail/posix_utility.hpp Fri Mar 27 18:52:17 2009 *************** *** 129,135 **** void * stack = ::mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, ! MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 ); --- 129,135 ---- void * stack = ::mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, ! MAP_PRIVATE /*|MAP_ANONYMOUS*/, -1, 0 ); *** boost/coroutine/detail/context_posix.hpp~ Sun Aug 20 13:11:09 2006 --- boost/coroutine/detail/context_posix.hpp Fri Mar 27 20:57:44 2009 *************** *** 42,47 **** --- 42,56 ---- * NOTE2: makecontext and friends are declared obsolescent in SuSv3, but * it is unlikely that they will be removed any time soon. */ + // NOTE3 (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html): + // > Why the bus error? What am I doing wrong? + // This is a known issue where getcontext(3) is writing past the end of the + // ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). + // As a workaround, define _XOPEN_SOURCE before including ucontext.h. + // [While we could make that OSX-specific, it seems harmless enough?] + #ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE + #endif #include <ucontext.h> #include <boost/noncopyable.hpp> #include <boost/coroutine/exception.hpp> // From http://hjiang.net/archives/220 #include <signal.h> #include <stdio.h> // NOTE (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html): // > Why the bus error? What am I doing wrong? // This is a known issue where getcontext(3) is writing past the end of the // ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). // As a workaround, define _XOPEN_SOURCE before including ucontext.h. // [While we could make that OSX-specific, it seems harmless enough?] #ifndef _XOPEN_SOURCE //#define _XOPEN_SOURCE #endif #include <ucontext.h> // Signals which routine should run. volatile int g_turn; void routineOne(ucontext_t* self, ucontext_t* other) { int numbers[] = {1, 2, 3}; int i; for (i = 0; i < sizeof(numbers)/sizeof(int); ++i) { printf("Routine one: %d\n", numbers[i]); // Call other with current continuation if (g_turn != 1) { g_turn = 1; swapcontext(self, other); } } } void routineTwo(ucontext_t* self, ucontext_t* other) { int numbers[] = {-1, -2, -3}; int i; for (i = 0; i < sizeof(numbers)/sizeof(int); ++i) { printf("Routine two: %d\n", numbers[i]); if (g_turn != 2) { g_turn = 2; swapcontext(self, other); } } } int main() { // Continuations ucontext_t cont_one; ucontext_t cont_two; ucontext_t cont_main; // one stack for each thread char stack_one[SIGSTKSZ]; char stack_two[SIGSTKSZ]; // Initialize the coutinuations. cont_one.uc_link = &cont_main; cont_one.uc_stack.ss_sp = stack_one; cont_one.uc_stack.ss_size = sizeof(stack_one); cont_two.uc_link = &cont_main; cont_two.uc_stack.ss_sp = stack_two; cont_two.uc_stack.ss_size = sizeof(stack_two); getcontext(&cont_one); makecontext(&cont_one, (void (*)())routineOne, 2, &cont_one, &cont_two); getcontext(&cont_two); makecontext(&cont_two, (void (*)())routineTwo, 2, &cont_two, &cont_one); g_turn = 0; // Call routineOne with current continuation. Continue from here // after routineOne finishes. getcontext(&cont_main); if (g_turn == 0) { setcontext(&cont_one); } return 0; }