cloudwu / coroutine

A asymmetric coroutine library for C.
MIT License
2.46k stars 688 forks source link

Assertion failed: (0), function coroutine_resume, file coroutine.c, line 155. 错误 #10

Open turbin opened 5 years ago

turbin commented 5 years ago

Mac OS 10.14.7版本。 gcc info: Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1 Apple LLVM version 10.0.1 (clang-1001.0.46.4) Target: x86_64-apple-darwin18.2.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin

在这个版本上编译,并运行代码生成的main 以后程序报告:

Assertion failed: (0), function coroutine_resume, file coroutine.c, line 155. 然后通过跟踪发现,main.c 里面

struct args arg1 = { 0 };
struct args arg2 = { 100 };

int co1 = coroutine_new(S, foo, &arg1);
int co2 = coroutine_new(S, foo, &arg2);

发现一个问题, struct coroutine 这个结构体的成员 ud 在程序resume coroutine的 co2的时候被修改了。

any idea for this?

Jeswang commented 4 years ago

遇到同样的问题,coroutine_resume(S,co1) 调用 getcontext 这个函数时会修改 co2 里的内容,我猜测 macOS 里定义了不同的 ucontext_t,占用的内存更大,转换的过程中访问越界了。

Jeswang commented 4 years ago

ok. 搞懂了。

首先,应该引入 #include ,而不是 <sys/ucontext.h>。因为使用到的函数并没有被声明在 <sys/ucontext.h> 里。因为某些原因编译通过了,但是类型估计是不同的。编译时加 flag 跳过检查:-D_XOPEN_SOURCE=600

其次,swapcontext 在 macOS 系统中的实现依赖于在栈上的返回地址,在调用 swapcontext 之前保存栈的信息会导致死循环。

苹果的实现见: https://github.com/Apple-FOSS-Mirror/Libc/blob/2ca2ae74647714acfc18674c3114b1a5d3325d7d/i386/gen/swapcontext.c

这里是我修改后可以跑通的代码(在同一个函数里保存和 swap 就行了): https://gist.github.com/Jeswang/4ae2b612f0c2da20265d1d6407b6cd2b

ssrlive commented 2 years ago

. @Jeswang 测试了一下,发现你的修改还是有问题,例子程序里有一句

printf("main end\n");

打印程序结束的信息,但是程序没有走到这里,说明中途出错了。整个程序的输出如下,供你参考。

coroutine % vi test.c
coroutine % gcc test.c -o test
test.c:74:8: warning: 'getcontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
        ret = getcontext(oucp);
              ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:38:6: note: 'getcontext' has been explicitly marked deprecated here
int  getcontext(ucontext_t *);
     ^
test.c:80:9: warning: 'setcontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
                ret = setcontext(ucp);
                      ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:44:6: note: 'setcontext' has been explicitly marked deprecated here
int  setcontext(const ucontext_t *);
     ^
test.c:111:8: warning: 'getcontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
        ret = getcontext(oucp);
              ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:38:6: note: 'getcontext' has been explicitly marked deprecated here
int  getcontext(ucontext_t *);
     ^
test.c:117:9: warning: 'setcontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
                ret = setcontext(ucp);
                      ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:44:6: note: 'setcontext' has been explicitly marked deprecated here
int  setcontext(const ucontext_t *);
     ^
test.c:216:3: warning: 'getcontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
                getcontext(&C->ctx);
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:38:6: note: 'getcontext' has been explicitly marked deprecated here
int  getcontext(ucontext_t *);
     ^
test.c:223:3: warning: 'makecontext' is deprecated: first deprecated in macOS 10.6 - No longer supported [-Wdeprecated-declarations]
                makecontext(&C->ctx, (void (*)(void)) mainfunc, 2, (uint32_t)ptr, (uint32_t)(ptr>>32));
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ucontext.h:41:6: note: 'makecontext' has been explicitly marked deprecated here
void makecontext(ucontext_t *, void (*)(), int, ...);
     ^
6 warnings generated.
coroutine % ./test
main start
coroutine 0 : 0
coroutine 1 : 100
coroutine 0 : 1
coroutine 1 : 101
coroutine 0 : 2
coroutine 1 : 102
coroutine 0 : 3
coroutine 1 : 103
coroutine 0 : 4
coroutine 1 : 104
coroutine % 

在苹果的源代码里没看出所以然来。

https://github.com/Apple-FOSS-Mirror/Libc/blob/master/x86_64/gen/swapcontext.c