Address boundary error when invoke swapcontext()

207 views Asked by At

I've written a simple program, use ucontext library. However, a signal SIGSEGV (address boundary error) occurred. The running env is MacOS. I do not know what's wrong I made?

Updated Here: Version 2

As @Jeremy suggest, we could use static on main_context and work_context. However, if we change work_context to an array, it still failed

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/time.h>
#include <unistd.h>

#define _XOPEN_SOURCE 600
#include "ucontext.h"


static ucontext_t main_context;
static ucontext_t work_context[3];  // version 2: from ucontext_t to an array

static void counter()
{
    for (int c = 0; ; c++) {
        fprintf(stderr, "c = %d\n", c);
        sleep(5);  // avoid busy loop
    }
}

static ucontext_t* make_context1(ucontext_t *ucp,  void (*func)())
{
    getcontext(ucp);
    sigemptyset(&ucp->uc_sigmask);

    void *sp = malloc(SIGSTKSZ);
    if (sp == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(-1);
    }
    ucp->uc_stack = (stack_t) { .ss_sp = sp, .ss_size = SIGSTKSZ, .ss_flags = 0 };
    ucp->uc_link = &main_context;
    
    makecontext(ucp, func, 0);
    return ucp;
}

int main() {
    printf("start\n");
    make_context1(work_context, counter);
    make_context1(work_context+1, counter);  // added in version 2
    make_context1(work_context+2, counter);  // added in version 2

    swapcontext(&main_context, work_context);
    printf("main exit\n");
    return 0;
}
2

There are 2 answers

1
KamilCuk On

Well, that's simple - SIGSTKSZ is too small of a stack for printf. Increase it. Quadruple it.

Move #define _XOPEN_SOURCE 600 on top of the file. See man feature_test_macros.

Add #include <signal.h> for sigemptyset. Change "ucontext.h" into <ucontext.h>- it's a standard header.

2
Jeremy Friesner On

For some reason the code runs without crashing if I change these two lines:

ucontext_t main_context;
ucontext_t work_context;

to this:

static ucontext_t main_context;
static ucontext_t work_context;

I'm sure there is a good explanation for this, but I don't know what it is :(