{"id":31,"date":"2019-12-10T18:55:42","date_gmt":"2019-12-10T16:55:42","guid":{"rendered":"http:\/\/www.juustila.com\/antti\/?p=31"},"modified":"2019-12-10T19:52:50","modified_gmt":"2019-12-10T17:52:50","slug":"remember-to-join","status":"publish","type":"post","link":"https:\/\/www.juustila.com\/antti\/2019\/12\/10\/remember-to-join\/","title":{"rendered":"Remember to join"},"content":{"rendered":"<p>When I forget to join (or detach) a C++ std::thread, it&#8217;ll crash with SIGABRT(6) on macOS. And obviously the stack dump does not tell me what is going on. So I hunt the bug for some hours, digging the log files, then finally remember that I just implemented a thread&#8230;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%\">***** FATAL SIGNAL RECEIVED *******\nReceived fatal signal: SIGABRT(6)\tPID: 17403\n\n***** SIGNAL SIGABRT(6)\n\n*******\tSTACKDUMP *******\n\tstack dump [1]  1   libg3logger.1.3.2-80.dylib          0x0000000100cb2163 _ZN12_GLOBAL__N_113signalHandlerEiP9__siginfoPv + 83\n\tstack dump [2]  2   libsystem_platform.dylib            0x00007fff72f73b1d _sigtramp + 29\n\tstack dump [3]  3   ???                                 0x0000000000000400 0x0 + 1024\n\tstack dump [4]  4   libsystem_c.dylib                   0x00007fff72e49a1c abort + 120\n\tstack dump [5]  5   libc++abi.dylib                     0x00007fff6fef2bc8 __cxa_bad_cast + 0\n\tstack dump [6]  6   libc++abi.dylib                     0x00007fff6fef2ca6 _ZL28demangling_terminate_handlerv + 48\n\tstack dump [7]  7   libc++abi.dylib                     0x00007fff6feffda7 _ZSt11__terminatePFvvE + 8\n\tstack dump [8]  8   libc++abi.dylib                     0x00007fff6feffd68 _ZSt9terminatev + 56\n\tstack dump [9]  9   BasicInfoGUI                        0x0000000100af1ffa _ZN11OHARStudent14StudentHandler8readFileEv + 42\n\tstack dump [10]  10  BasicInfoGUI                        0x0000000100af28df _ZN11OHARStudent14StudentHandler7consumeERN8OHARBase7PackageE + 2223\n\tstack dump [11]  11  BasicInfoGUI                        0x0000000100a6d101 _ZN8OHARBase13ProcessorNode14passToHandlersERNS_7PackageE + 897\n\tstack dump [12]  12  BasicInfoGUI                        0x0000000100a6a69e _ZN8OHARBase13ProcessorNode10threadFuncEv + 2462\n\tstack dump [13]  13  BasicInfoGUI                        0x0000000100a79061 _ZNSt3__1L8__invokeIMN8OHARBase13ProcessorNodeEFvvEPS2_JEvEEDTcldsdeclsr3std3__1E7forwardIT0_Efp0_Efp_spclsr3std3__1E7forwardIT1_Efp1_EEEOT_OS6_DpOS7_ + 113\n\tstack dump [14]  14  BasicInfoGUI                        0x0000000100a78f6e _ZNSt3__1L16__thread_executeINS_10unique_ptrINS_15__thread_structENS_14default_deleteIS2_EEEEMN8OHARBase13ProcessorNodeEFvvEJPS7_EJLm2EEEEvRNS_5tupleIJT_T0_DpT1_EEENS_15__tuple_indicesIJXspT2_EEEE + 62\n\tstack dump [15]  15  BasicInfoGUI                        0x0000000100a78796 _ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEMN8OHARBase13ProcessorNodeEFvvEPS8_EEEEEPvSD_ + 118\n\tstack dump [16]  16  libsystem_pthread.dylib             0x00007fff72f7ed36 _pthread_start + 125\n\tstack dump [17]  17  libsystem_pthread.dylib             0x00007fff72f7b58f thread_start + 15\n\nExiting after fatal event  (FATAL_SIGNAL). Fatal type:  SIGABRT\nLog content flushed sucessfully to sink\n<\/pre>\n<\/div>\n<p>So I am writing this down, just to remember next time. Join or detach. Join or detach&#8230;.<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #272822; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\">   <span style=\"color: #66d9ef;\">void<\/span> <span style=\"color: #f8f8f2;\">StudentHandler<\/span><span style=\"color: #f92672;\">::<\/span><span style=\"color: #f8f8f2;\">readFile()<\/span> <span style=\"color: #f8f8f2;\">{<\/span>\n      <span style=\"color: #f8f8f2;\">std<\/span><span style=\"color: #f92672;\">::<\/span><span style=\"color: #66d9ef;\">thread<\/span><span style=\"color: #f8f8f2;\">(<\/span> <span style=\"color: #f8f8f2;\">[<\/span><span style=\"color: #66d9ef;\">this<\/span><span style=\"color: #f8f8f2;\">]<\/span> <span style=\"color: #f8f8f2;\">{<\/span>\n         <span style=\"color: #f8f8f2;\">StudentFileReader<\/span> <span style=\"color: #f8f8f2;\">reader(<\/span><span style=\"color: #f92672;\">*<\/span><span style=\"color: #66d9ef;\">this<\/span><span style=\"color: #f8f8f2;\">);<\/span>\n         <span style=\"color: #66d9ef;\">using<\/span> <span style=\"color: #66d9ef;\">namespace<\/span> <span style=\"color: #f8f8f2;\">std<\/span><span style=\"color: #f92672;\">::<\/span><span style=\"color: #f8f8f2;\">chrono_literals;<\/span>\n         <span style=\"color: #f8f8f2;\">std<\/span><span style=\"color: #f92672;\">::<\/span><span style=\"color: #f8f8f2;\">this_thread<\/span><span style=\"color: #f92672;\">::<\/span><span style=\"color: #f8f8f2;\">sleep_for(<\/span><span style=\"color: #ae81ff;\">50<\/span><span style=\"color: #f8f8f2;\">ms);<\/span>\n         <span style=\"color: #f8f8f2;\">reader.read(node.getDataFileName());<\/span>\n      <span style=\"color: #f8f8f2;\">}).join();<\/span>\n   <span style=\"color: #f8f8f2;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><em>Edit:<\/em> Actually, I changed <code>join()<\/code> to <code>detach()<\/code>. With join, the calling thread <em>waited<\/em> for this file reading thread to finish before continuing to handle incoming data from network. The file was read totally in memory, and <em>only then<\/em> data from network was combined with data from file and send ahead to next node in the network. With 5000 test records, all of them were held in memory waiting for the data from network to arrive when using <code>join()<\/code>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When I switched to use <code>detach()<\/code>, calling thread could <em>continue reading data from network<\/em>, while simultaneously file reading thread was reading data from file. Whenever a match was found in a list, either one of these threads, the data was combined and send ahead to the next node in the network. So with join, maximum of 5000 records were held in memory all the time, as with detach(), about 1300-1800 records were held in memory at most. Because combined data could be send ahead to next node in the network and discarded from this node. A significant change in the amount of memory the nodes use. So it does matter which you use, depending on the purpose of the threads in your app.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I forget to join (or detach) a C++ std::thread, it&#8217;ll crash with SIGABRT(6) on macOS. And obviously the stack dump does not tell me what is going on. So I hunt the bug for some hours, digging the log files, then finally remember that I just implemented a thread&#8230; ***** FATAL SIGNAL RECEIVED ******* &hellip; <a href=\"https:\/\/www.juustila.com\/antti\/2019\/12\/10\/remember-to-join\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Remember to join&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[2],"tags":[10,11,9,8],"class_list":["post-31","post","type-post","status-publish","format-standard","hentry","category-coding","tag-c","tag-cstd","tag-sigabrt","tag-stdthread"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/31","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/comments?post=31"}],"version-history":[{"count":3,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/31\/revisions"}],"predecessor-version":[{"id":35,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/31\/revisions\/35"}],"wp:attachment":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/media?parent=31"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/categories?post=31"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/tags?post=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}