yourWaifu / sleepy-discord

C++ library for the Discord chat client. Please use Rust for new bots
https://yourWaifu.github.io/sleepy-discord/
MIT License
707 stars 95 forks source link

HTTP Error on sendMessage in client event handler sometimes causes SIGABRT #204

Closed yappy closed 3 years ago

yappy commented 3 years ago

I wrote a onMessage event handler, which calls sendMessage() to reply. (simply like example) sendMessage() may throw an enum (from client.cpp:154), sometimes client->run() throws it and I could catch it and re-run, but sometimes the event handler is called from asio internal thread and it causes crash. (SIGABRT)

Example: sendMessage() throws SleepyDiscord::ErrorCode See # 6 and # 23.

[New Thread 0xab3f7220 (LWP 11637)]
[Thread 0xab3f7220 (LWP 11637) exited]
Sun Jan 31 05:54:28 2021 (2931810848) [Error]: [Discord] You've made too many requests
Sun Jan 31 05:54:28 2021 (2931810848) [Error]: [Discord] {
  "global": false,
  "message": "You are being rate limited.",
  "retry_after": 4264
}

terminate called after throwing an instance of 'SleepyDiscord::ErrorCode'

Thread 18 "shanghai" received signal SIGABRT, Aborted.
[Switching to Thread 0xaebfe220 (LWP 11531)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50      ../sysdeps/unix/sysv/linux/raise.c: そのようなファイルやディレクトリはありません.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0xb6919230 in __GI_abort () at abort.c:79
#2  0xb6b9d8d8 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#3  0xb6b9b5b0 in ?? () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#4  0xb6b9b624 in std::terminate() () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#5  0xb6b9b990 in __cxa_throw () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
/////////////////////////////////////////
/// !!! throw enum here !!!
/////////////////////////////////////////
#6  0x000cc204 in SleepyDiscord::BaseDiscordClient::request(SleepyDiscord::RequestMethod, SleepyDiscord::Route, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<SleepyDiscord::Part, std::allocator<SleepyDiscord::Part> > const&, std::function<void (SleepyDiscord::Response)>, SleepyDiscord::RequestMode) (
    this=0x2e6818, method=SleepyDiscord::Post, path=...,
    jsonParameters="{\"content\":\"🀈🀋🀚🀛🀜🀜🀐🀒🀁🀂🀂🀆🀅🀄\"}",
    multipartParameters=std::vector of length 0, capacity 0, callback=..., mode=SleepyDiscord::Sync_AsyncQueue)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/sleepy_discord/client.cpp:154
#7  0x0010f274 in SleepyDiscord::BaseDiscordClient::request<SleepyDiscord::BaseDiscordClient::RequestSettings<SleepyDiscord::ObjectResponse<SleepyDiscord::Message> > > (this=0x2e6818, method=SleepyDiscord::Post, path=..., settings=...,
    jsonParameters="{\"content\":\"🀈🀋🀚🀛🀜🀜🀐🀒🀁🀂🀂🀆🀅🀄\"}",
    multipartParameters=...)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/include/sleepy_discord/client.h:202
#8  0x000fd9bc in SleepyDiscord::BaseDiscordClient::sendMessage (this=0x2e6818, channelID=...,
    message="🀈🀋🀚🀛🀜🀜🀐🀒🀁🀂🀂🀆🀅🀄", embed=..., tts=false, settings=...)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/sleepy_discord/endpoints.cpp:33
#9  0x000419a4 in shanghai::system::Discord::MyClient::ExecuteCommand (this=0x2e6818, ch=...,
    args=std::vector of length 1, capacity 1 = {...})
    at /home/yappy/workspace/DollsKit/shanghai/src/system/discord.cpp:189
#10 0x000422d8 in shanghai::system::Discord::MyClient::onMessage (this=0x2e6818, message=...)
    at /home/yappy/workspace/DollsKit/shanghai/src/system/discord.cpp:234
#11 0x000d0424 in SleepyDiscord::BaseDiscordClient::processMessage (this=0x2e6818,
    message="{\"t\":\"MESSAGE_CREATE\",\"s\":44,\"op\":0,\"d\":{\"type\":0,\"tts\":false,\"timestamp\":\"2021-01-30T20:54:27.035000+00:00\",\"referenced_message\":null,\"pinned\":false,\"nonce\":\"805179118894186496\",\"mentions\":[{\"usernam"...) at /home/yappy/workspace/DollsKit/external/sleepy-discord/sleepy_discord/client.cpp:574
#12 0x00150618 in SleepyDiscord::WebsocketppDiscordClient::<lambda()>::operator()(void) const (__closure=0xb2a1e5f0)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/sleepy_discord/websocketpp_websocket.cpp:161
#13 0x0015123c in std::_Function_handler<void(), SleepyDiscord::WebsocketppDiscordClient::onMessage(websocketpp::connection_hdl, websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager>::ptr, SleepyDiscord::GenericMessageReceiver*)::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...)
    at /usr/include/c++/8/bits/std_function.h:297
#14 0x00043dc4 in std::function<void ()>::operator()() const (this=0xaebfdafc)
    at /usr/include/c++/8/bits/std_function.h:687
#15 0x0004bf34 in asio::asio_handler_invoke<std::function<void ()> >(std::function<void ()>&, ...) (function=...)
--Type <RET> for more, q to quit, c to continue without paging--
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/handler_invoke_hook.hpp:68
#16 0x0004b058 in asio_handler_invoke_helpers::invoke<std::function<void ()>, std::function<void ()> >(std::function<void ()>&, std::function<void ()>&) (function=..., context=...)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/handler_invoke_helpers.hpp:37
#17 0x00049870 in asio::detail::executor_op<std::function<void ()>, std::allocator<void>, asio::detail::scheduler_operation>::do_complete(void*, asio::detail::scheduler_operation*, std::error_code const&, unsigned int) (owner=0xb2a07298,
    base=0xb2a06d90)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/executor_op.hpp:69
#18 0x0003c330 in asio::detail::scheduler_operation::complete (this=0xb2a06d90, owner=0xb2a07298, ec=...,
    bytes_transferred=0)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/scheduler_operation.hpp:39
#19 0x0003e2b0 in asio::detail::scheduler::do_run_one (this=0xb2a07298, lock=..., this_thread=..., ec=...)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/impl/scheduler.ipp:400
#20 0x0003dee0 in asio::detail::scheduler::run (this=0xb2a07298, ec=...)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/impl/scheduler.ipp:153
#21 0x0003e814 in asio::system_context::thread_function::operator() (this=0xb2a0e38c)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/impl/system_context.ipp:32
#22 0x00052274 in asio::detail::posix_thread::func<asio::system_context::thread_function>::run (this=0xb2a0e388)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/posix_thread.hpp:85
//////////////////////////////////////////////////////////////////////////////////
/// !!! looks like pthread created in asio library !!!
//////////////////////////////////////////////////////////////////////////////////
#23 0x0003e6a8 in asio::detail::asio_detail_posix_thread_function (arg=0xb2a0e388)
    at /home/yappy/workspace/DollsKit/external/sleepy-discord/deps/asio/asio/include/asio/detail/impl/posix_thread.ipp:73
#24 0xb6a56494 in start_thread (arg=0xaebfe220) at pthread_create.c:486
#25 0xb69d9578 in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:73 from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
yappy commented 3 years ago

I'm using cmake default configuration. (websocketpp) SleepyDiscord::USER_CONTROLED_THREADS (=1)

yourWaifu commented 3 years ago

Looks like a error wasn't handled. You can turn off the throw when making a request but I would recommend doing a try catch or an if error. here's some pseudocode examples:

try {
    Message  mess = send Message();

Or

auto mmm = send Message ();
if(mmm.error()) {

Or

Message mess;
If(send message().cast(mess)) {

some of these require changing the request mode to work tho, here's a list of them https://github.com/yourWaifu/sleepy-discord/blob/7796a1fd6003eb75511068e0c206aaada6198213/include/sleepy_discord/client.h#L88-L98

yappy commented 3 years ago

Thanks, understood. I confirmed that request mode default is Sync_AsyncQueue and it includes ThrowError bit.

https://github.com/yourWaifu/sleepy-discord/blob/7796a1fd6003eb75511068e0c206aaada6198213/include/sleepy_discord/client.h#L126-L131