Skip to content

Commit 18be132

Browse files
Merge pull request #128 from Huberyxiao/huberyxxiao-fixcrash
fix: 主程序结束早于异步任务导致的crash
2 parents 18eead9 + 1a4ca33 commit 18be132

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

demo/cos_demo.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "cos_sys_config.h"
1919
#include "util/auth_tool.h"
2020

21+
#include "Poco/TaskManager.h"
22+
2123
using namespace qcloud_cos;
2224
void PrintResult(const qcloud_cos::CosResult& result,
2325
const qcloud_cos::BaseResp& resp) {
@@ -1686,9 +1688,52 @@ void AsyncMultiGetObject(qcloud_cos::CosAPI& cos,
16861688
std::cout << "AsyncMultiGetObject failed" << std::endl;
16871689
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
16881690
}
1691+
//context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
1692+
//此时您的主线程如果立即结束,异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
1693+
//此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
1694+
//可以采用此策略避免crash。
1695+
//或者可以采用下方AsyncMultiGetObjectWithTaskManager函数中的方式,使用能透传TaskManager的接口,使用join的方式避免crash。
16891696
std::this_thread::sleep_for(std::chrono::seconds(1));
16901697
}
16911698

1699+
// 异步下载对象,支持更新下载进度
1700+
// 回传taskManager对象,可用使用它等待异步线程彻底结束
1701+
void AsyncMultiGetObjectWithTaskManager(qcloud_cos::CosAPI& cos,
1702+
const std::string& bucket_name,
1703+
const std::string& object_name,
1704+
const std::string& file_path) {
1705+
qcloud_cos::AsyncMultiGetObjectReq req(bucket_name, object_name, file_path);
1706+
// 设置进度回调
1707+
req.SetTransferProgressCallback(&ProgressCallback);
1708+
// 设置状态回调
1709+
req.SetDoneCallback(&MultiGetObjectAsyncDoneCallback);
1710+
// 设置私有数据
1711+
req.SetUserData(&req);
1712+
1713+
// 开始下载
1714+
Poco::TaskManager* taskManager;
1715+
qcloud_cos::SharedAsyncContext context = cos.AsyncMultiGetObject(req,taskManager);
1716+
1717+
// 等待下载结束
1718+
context->WaitUntilFinish();
1719+
1720+
// 检查结果
1721+
if (context->GetResult().IsSucc()) {
1722+
// 获取响应
1723+
std::cout << "AsyncMultiGetObject succeed" << std::endl;
1724+
std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
1725+
AsyncResp resp = context->GetAsyncResp();
1726+
std::cout << "ETag:" << resp.GetEtag() << std::endl;
1727+
std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
1728+
} else {
1729+
std::cout << "AsyncMultiGetObject failed" << std::endl;
1730+
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
1731+
}
1732+
1733+
// 使用taskManager等待异步线程彻底结束
1734+
(*taskManager).joinAll();
1735+
}
1736+
16921737
static void MultiPutObjectAsyncDoneCallback(const SharedAsyncContext& context,
16931738
void* user_data) {
16941739
UNUSED_PARAM(user_data)

include/cos_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "op/service_op.h"
88
#include "util/auth_tool.h"
99
#include "util/codec_util.h"
10+
#include "Poco/TaskManager.h"
1011

1112
namespace qcloud_cos {
1213

@@ -722,24 +723,29 @@ class CosAPI {
722723
/// \param req PutObjectAsync请求
723724
/// \return 返回context
724725
SharedAsyncContext AsyncPutObject(const AsyncPutObjectReq& req);
726+
SharedAsyncContext AsyncPutObject(const AsyncPutObjectReq& req, Poco::TaskManager*& taskManager);
725727

726728
SharedAsyncContext AsyncPutObject(const AsyncPutObjectByStreamReq& req);
729+
SharedAsyncContext AsyncPutObject(const AsyncPutObjectByStreamReq& req, Poco::TaskManager*& taskManager);
727730

728731
/// \brief
729732
/// 异步上传对象,封装了初始化分块上传、分块上传、完成分块上传三步,支持断点续传
730733
/// \param req MultiPutObjectAsync请求
731734
/// \return 返回context
732735
SharedAsyncContext AsyncMultiPutObject(const AsyncMultiPutObjectReq& req);
736+
SharedAsyncContext AsyncMultiPutObject(const AsyncMultiPutObjectReq& req, Poco::TaskManager*& taskManager);
733737

734738
/// \brief 异步单线程下载对象到本地
735739
/// \param req GetObjectAsync请求
736740
/// \return 返回context
737741
SharedAsyncContext AsyncGetObject(const AsyncGetObjectReq& req);
742+
SharedAsyncContext AsyncGetObject(const AsyncGetObjectReq& req, Poco::TaskManager*& taskManager);
738743

739744
/// \brief 异步多线程下载对象到本地
740745
/// \param req MultiGetObjectAsync请求
741746
/// \return 返回context
742747
SharedAsyncContext AsyncMultiGetObject(const AsyncMultiGetObjectReq& req);
748+
SharedAsyncContext AsyncMultiGetObject(const AsyncMultiGetObjectReq& req, Poco::TaskManager*& taskManager);
743749

744750
/* 批量及目录操作接口 */
745751

src/cos_api.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,20 @@ SharedAsyncContext CosAPI::AsyncPutObject(const AsyncPutObjectReq& req) {
502502
return context;
503503
}
504504

505+
SharedAsyncContext CosAPI::AsyncPutObject(const AsyncPutObjectReq& req, Poco::TaskManager*& taskManager) {
506+
SharedTransferHandler handler(new TransferHandler());
507+
handler->SetRequest(reinterpret_cast<const void*>(&req));
508+
handler->SetTotalSize(req.GetLocalFileSize());
509+
TaskFunc fn = [=]() {
510+
PutObjectByFileResp resp;
511+
m_object_op.PutObject(req, &resp, handler);
512+
};
513+
taskManager = &GetGlobalTaskManager();
514+
(*taskManager).start(new AsyncTask(std::move(fn)));
515+
SharedAsyncContext context(new AsyncContext(handler));
516+
return context;
517+
}
518+
505519
SharedAsyncContext CosAPI::AsyncPutObject(const AsyncPutObjectByStreamReq& req) {
506520
SharedTransferHandler handler(new TransferHandler());
507521
handler->SetRequest(reinterpret_cast<const void*>(&req));
@@ -518,6 +532,23 @@ SharedAsyncContext CosAPI::AsyncPutObject(const AsyncPutObjectByStreamReq& req)
518532
return context;
519533
}
520534

535+
SharedAsyncContext CosAPI::AsyncPutObject(const AsyncPutObjectByStreamReq& req, Poco::TaskManager*& taskManager) {
536+
SharedTransferHandler handler(new TransferHandler());
537+
handler->SetRequest(reinterpret_cast<const void*>(&req));
538+
auto& is = req.GetStream();
539+
is.seekg(0, std::ios::end);
540+
handler->SetTotalSize(is.tellg());
541+
is.seekg(0, std::ios::beg);
542+
TaskFunc fn = [=]() {
543+
PutObjectByStreamResp resp;
544+
m_object_op.PutObject(req, &resp, handler);
545+
};
546+
taskManager = &GetGlobalTaskManager();
547+
(*taskManager).start(new AsyncTask(std::move(fn)));
548+
SharedAsyncContext context(new AsyncContext(handler));
549+
return context;
550+
}
551+
521552

522553
SharedAsyncContext CosAPI::AsyncMultiPutObject(const AsyncMultiPutObjectReq& req) {
523554
SharedTransferHandler handler(new TransferHandler());
@@ -532,6 +563,20 @@ SharedAsyncContext CosAPI::AsyncMultiPutObject(const AsyncMultiPutObjectReq& req
532563
return context;
533564
}
534565

566+
SharedAsyncContext CosAPI::AsyncMultiPutObject(const AsyncMultiPutObjectReq& req, Poco::TaskManager*& taskManager) {
567+
SharedTransferHandler handler(new TransferHandler());
568+
handler->SetRequest(reinterpret_cast<const void*>(&req));
569+
handler->SetTotalSize(req.GetLocalFileSize());
570+
TaskFunc fn = [=]() {
571+
MultiPutObjectResp resp;
572+
m_object_op.MultiUploadObject(req, &resp, handler);
573+
};
574+
taskManager = &GetGlobalTaskManager();
575+
(*taskManager).start(new AsyncTask(std::move(fn)));
576+
SharedAsyncContext context(new AsyncContext(handler));
577+
return context;
578+
}
579+
535580
SharedAsyncContext CosAPI::AsyncGetObject(const AsyncGetObjectReq& req) {
536581
SharedTransferHandler handler(new TransferHandler());
537582
handler->SetRequest(reinterpret_cast<const void*>(&req));
@@ -544,6 +589,19 @@ SharedAsyncContext CosAPI::AsyncGetObject(const AsyncGetObjectReq& req) {
544589
return context;
545590
}
546591

592+
SharedAsyncContext CosAPI::AsyncGetObject(const AsyncGetObjectReq& req, Poco::TaskManager*& taskManager) {
593+
SharedTransferHandler handler(new TransferHandler());
594+
handler->SetRequest(reinterpret_cast<const void*>(&req));
595+
TaskFunc fn = [=]() {
596+
GetObjectByFileResp resp;
597+
m_object_op.GetObject(req, &resp, handler);
598+
};
599+
taskManager = &GetGlobalTaskManager();
600+
(*taskManager).start(new AsyncTask(std::move(fn)));
601+
SharedAsyncContext context(new AsyncContext(handler));
602+
return context;
603+
}
604+
547605
SharedAsyncContext CosAPI::AsyncMultiGetObject(const AsyncMultiGetObjectReq& req) {
548606
SharedTransferHandler handler(new TransferHandler());
549607
handler->SetRequest(reinterpret_cast<const void*>(&req));
@@ -556,6 +614,19 @@ SharedAsyncContext CosAPI::AsyncMultiGetObject(const AsyncMultiGetObjectReq& req
556614
return context;
557615
}
558616

617+
SharedAsyncContext CosAPI::AsyncMultiGetObject(const AsyncMultiGetObjectReq& req, Poco::TaskManager*& taskManager) {
618+
SharedTransferHandler handler(new TransferHandler());
619+
handler->SetRequest(reinterpret_cast<const void*>(&req));
620+
TaskFunc fn = [=]() {
621+
GetObjectByFileResp resp;
622+
m_object_op.MultiThreadDownload(req, &resp, handler);
623+
};
624+
taskManager = &GetGlobalTaskManager();
625+
(*taskManager).start(new AsyncTask(std::move(fn)));
626+
SharedAsyncContext context(new AsyncContext(handler));
627+
return context;
628+
}
629+
559630
CosResult CosAPI::PutObjects(const PutObjectsByDirectoryReq& req,
560631
PutObjectsByDirectoryResp* resp) {
561632
return m_object_op.PutObjects(req, resp);

0 commit comments

Comments
 (0)