Boost logo

Boost Users :

Subject: [Boost-users] [coroutine] Bus error on Mac OS X 10.5
From: Nat Goodspeed (nat_at_[hidden])
Date: 2009-03-27 22:20:56


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-coroutine.tar.gz&directory=Concurrent%20Programming&
[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;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net