te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>c++ - Thread crash during boost::yield inside catch block - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Thread crash during boost::yield inside catch block - Stack Overflow

programmeradmin3浏览0评论

I'm currently investigating a crash scenario that is caused by performing a Boost yield inside a C++ catch block. Here's a minimal reproducible example that leads to a crash. Notice the following points :

  1. Multiple threads in a thread_group are needed to reproduce the crash.
  2. 2 coroutine must be running simultaneously.
  3. When yielding outside the catch block, everything works as expected.
  4. Issue reproduced consistently on both Mac/Win platforms (linux wasn't tested).
  5. When debugging the crash, the call stack was pointing on the yield inside the catch block.
  6. I've found this old forum that mentions a similar issue, but the explanation is unclear to me : .php

Here's a standalone reproduction example. Unfortunately I wasn't to make it shorter, but you can simply run it as-is linked to boost version 1.86-1.83

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/thread.hpp>
#include <iostream>

namespace asio = boost::asio;
using namespace std::chrono_literals;

void TimerCatchYield(asio::steady_timer& timer,
                     const asio::yield_context& yield) {
  boost::system::error_code ec;
  try {
    throw std::runtime_error("");
  } catch (const std::exception&) {
    // async_wait(yield) here - causes crash
    timer.async_wait(yield[ec]);
  }
  // async_wait(yield) here - works as expected
}

void coroutineA(asio::steady_timer& timer, const asio::yield_context& yield) {
  std::cout << "Coroutine A: Starting timer...\n";

  timer.expires_after(500ms);
  TimerCatchYield(timer, yield);
  std::cout << "Coroutine A: 1\n";

  timer.expires_after(500ms);
  TimerCatchYield(timer, yield);
  std::cout << "Coroutine A: 2\n";

  timer.expires_after(500ms);
  TimerCatchYield(timer, yield);
  std::cout << "Coroutine A: 3\n";

  std::cout << "Coroutine A: all timers expired\n";
}

void coroutineB(asio::steady_timer& timer, const asio::yield_context& yield) {
  std::cout << "Coroutine B: Starting timer...\n";
  boost::system::error_code ec;

  timer.expires_after(500ms);
  timer.async_wait(yield[ec]);
  std::cout << "Coroutine B: 1\n";

  timer.expires_after(500ms);
  timer.async_wait(yield[ec]);
  std::cout << "Coroutine B: 2\n";

  timer.expires_after(500ms);
  timer.async_wait(yield[ec]);
  std::cout << "Coroutine B: 3\n";

  std::cout << "Coroutine B: all timers expired\n";
}

int main() {
  asio::io_context io;
  asio::steady_timer timerA(io);
  asio::steady_timer timerB(io);

  auto strand = make_strand(io);

  boost::thread_group threads;

  spawn(strand,
        [&](const asio::yield_context& yield) { coroutineA(timerA, yield); });

  spawn(strand, [&](const asio::yield_context& yield_b) {
    coroutineB(timerB, yield_b);
  });

  for (int i = 0; i < 4; ++i) {
    threads.create_thread([&io]() { io.run(); });
  }

  threads.join_all();

  std::cout << "Main finished\n";
  return 0;
}
发布评论

评论列表(0)

  1. 暂无评论