co_http icon indicating copy to clipboard operation
co_http copied to clipboard

!ret.is_error(EAGAIN) 中 为什么需要调用return cb(ret);

Open gknagoing opened this issue 1 year ago • 2 comments

function:async_accept
......
       auto ret =
           convert_error<int>(accept(m_fd, &addr.m_addr, &addr.m_addrlen));
       if (!ret.is_error(EAGAIN)) {
           stop.clear_stop_callback();
           cb(ret);//Server不会报错 和 chat_Server会报错
           //return cb(ret);//Server 和 chat_Server都不会报错
           //return;//Server会报错 和 chat_Server会报错
       }

这里为什么必须调用cb(ret) 且需要return? 有没有大佬能够帮忙解释一下发生了什么?

gknagoing avatar Sep 12 '24 10:09 gknagoing

完整代码:

        auto ret =
            convert_error<int>(accept(m_fd, &addr.m_addr, &addr.m_addrlen));
        if (!ret.is_error(EAGAIN)) {
            stop.clear_stop_callback();
            return cb(ret);
        }

        // 如果 accept 到请求了,请操作系统,调用,我这个回调
        return _epoll_callback(
            [this, &addr, cb = std::move(cb), stop]() mutable {
                return async_accept(addr, std::move(cb), stop);
            },
            EPOLLIN | EPOLLERR | EPOLLET | EPOLLONESHOT, stop);

archibate avatar Sep 13 '24 03:09 archibate

return cb(ret)等价于: cb(ret); return; 如果没有这个early-return,那么就会执行到后面的_epoll_callback了,就会继续等待accept就绪。 然而只有当返回错误为EAGAIN时,才代表是因为“没有就绪”导致错误。 如果是其他错误,则应该直接返回错误,而不是继续_epoll_callback注册回调继续等待就绪,否则会死循环。 所以,必须要有return; 那么,为什么还要cb(ret)?无论错误与否,都需要返回,你可能误解成只有成功才会返回了。 即使发生了错误(除了EAGAIN这个特殊错误外),一样需要告诉调用者设置的回调,通过传入负数的方式。 一些语言的async函数则是支持双回调,出错一个回调,正常成功一个回调,例如javascript的Promise,有callback和reject两个回调,正常业务逻辑在callback里处理即可。而我的co_http没有采用分离回调的设计(boost.asio也没有),需要回调函数cb里自己if判断一下ret是否出错。

archibate avatar Sep 13 '24 03:09 archibate