promise-cpp icon indicating copy to clipboard operation
promise-cpp copied to clipboard

嵌套promise在析构时候会抛异常

Open Cirnoo opened this issue 3 years ago • 3 comments

test0.cpp中有如下示例

.then([&next](){
        output_func_name();
        next= newPromise([](Defer d) {
            output_func_name();
            //尝试调用d.resolve(1, 'c');
        });
        //尝试调用 next.resolve();,或next.resolve(1, 'c');
        //Will call next.resole() or next.reject() later
        //throw 33;
        //next.reject(55, 66);
        return next;
    })

如果增加next.resolve();或者d.resolve(); 会产生bad_any_cast异常,导致promiseHolder->state_ = TaskState::kRejected,在析构时会走到全局异常handler中。

我想通过创建一个新的newPromise的方式,内部切线程异步处理完成后再回调到下个then,这样看起来会有问题。

Cirnoo avatar Feb 08 '22 12:02 Cirnoo

抓到异常是对的,因为resolve/reject需要下一级的 then/fail 函数捕获。 如果参数类型不一样,无法捕获,就抛异常了。可以这样试下

 .then([&next](){
        output_func_name();
        next = newPromise([](Defer d) {
            output_func_name();
        });
        next.resolve(1, 'c');
        return next;
    }).then([](int a, char b) {
        printf("a = %d, b = %d\n", a, (int)b);
    })

或者捕获任意参数类型,可以将 a, b参数去掉

 .then([&next](){
        output_func_name();
        next = newPromise([](Defer d) {
            output_func_name();
        });
        next.resolve(1, 'c');
        return next;
    }).then([]() {
        printf("运行到这里\n");
    })

xhawk18 avatar Feb 08 '22 13:02 xhawk18

线程切换回来再调用,应该问题不大。 因为:

  1. 任务链实例析构时,代码会根据需要做出判断,是否要调用 ”全局异常handler“。只要保证任务链实例还在,就不会走到全局异常。

  2. next或d内部,都通过shared_ptr的方式,保存了任务链实例。

  3. 线程切换回来调用,必定要保障 next或d至少有一个(或其复制品)还能访问到。(对比一楼的状况,next和d都被析构了,内部的任务链也析构了,于是走到全局异常。)

xhawk18 avatar Feb 08 '22 14:02 xhawk18

感谢你的回复,除了你指出的问题,还有是示例代码后面的then类型未匹配

.then([](int n, char c) {
        output_func_name();
        printf("n = %d, c = %c\n", (int)n, c);
    }).then([](char n) {
        output_func_name();
        printf("n = %d\n", (int)n);
    })

第一个then的return是void和第二个then的入参不一致~,补充上resolve('0')就没有异常了

Cirnoo avatar Feb 08 '22 17:02 Cirnoo