简体   繁体   中英

How do I inform the compiler that `getcontext` can return multiple times?

getcontext can return multiple times. For example, I have sketched a C program analogous to the one demostrated here :

#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <ucontext.h>

struct communication {
        const ucontext_t *return_ctx;
        int return_value;
};

static void
test(ucontext_t *thisctx, struct communication *comm)
{
        int i = 0;
        assert(getcontext(thisctx) == 0);
        // getcontext will return 3 times with i having different values

        comm->return_value = ++i;
        setcontext(comm->return_ctx);
        assert(0);
}

int
main(void)
{
        ucontext_t mainctx, testctx;
        struct communication comm;
        char test_stack[SIGSTKSZ];

        assert(getcontext(&testctx) == 0);
        testctx.uc_stack.ss_sp = test_stack;
        testctx.uc_stack.ss_size = sizeof test_stack;
        makecontext(&testctx, test, 2,
                &testctx, &comm);

        for (int i = 0; i < 3; ++i) {
                // Rewind test's execution where 'getcontext' returns
                comm.return_ctx = &mainctx;
                assert(swapcontext(&mainctx, &testctx) == 0);
                assert(printf("%d\n", comm.return_value) > 0);
        }

        return 0;
}

Compiling and running it

$ gcc -std=gnu99 -O3 -o getcontext_test getcontext_test.c
$ ./getcontext_test
1
1
1

does not give expected 1 2 3 because the compiler thinks that i can only equal 1 when assigned to comm->return_value .

I can work this around by defining i volatile , however I would like a more canonical approach to this issue.

A necessary (but maybe not sufficient) requirement for what you want is making i (in the test function; the duplication of name between functions of the identifier you're asking about is unfortunate) volatile . This is already a requirement in the standard (7.13.2.1 ¶3):

All accessible objects have values, and all other components of the abstract machine have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate.

for objects that may be modified between successive returns of setjmp , so it makes perfectly good sense that you should (and should have to) do the same thing with getcontext .

For other reasons, it may be necessary for the compiler to be aware that getcontext return more than once. On GCC and compatible compilers (most anything but MSVC), you can achieve this with __attribute__((__returns_twice__)) . However, the header that declared getcontext (or compiler internals) should already be doing something like this if it's needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM