2013-07-04 112 views
-1

兩種不同的dlopen & dlclose夫婦,在dlopen上被封鎖。dlopen/dlclose與夫婦如此,封鎖在dlopen上

掛在dlopen,它不輸出任何內容,cpuidle降到0%,並且不能通過ctrl + c退出。

LOG_TRACE("attaching..."); 
handle = dlopen(plugin_path.c_str(), RTLD_LAZY); 
LOG_DEBUG("dlopen called");  // this line did not output, after success couple of times; 

然後我用GDB附加到程序:

(gdb) bt 
#0 0x0000002a960dbe60 in tcmalloc::ThreadCache::InitTSD() at src/thread_cache.cc:321 
#1 0x0000002a960d51bf in TCMallocGuard (this=Variable "this" is not available.) at src/tcmalloc.cc:908 
#2 0x0000002a960d5e00 in global constructors keyed to _ZN61FLAG__namespace_do_not_use_directly_use_DECLARE_int64_instead43FLAGS_tcmalloc_large_alloc_report_thresholdE() at src/tcmalloc.cc:935 
#3 0x0000002a960fafc6 in __do_global_ctors_aux() at ./src/base/spinlock.h:54 
#4 0x0000002a96010f13 in _init() from ../plugins/libmonitor.so 
#5 0x0000002a00000000 in ??() 
#6 0x000000302ad0acaf in _dl_init_internal() from /lib64/ld-linux-x86-64.so.2 
#7 0x000000302aff725c in dl_open_worker() from /lib64/tls/libc.so.6 
#8 0x000000302ad0aa60 in _dl_catch_error() from /lib64/ld-linux-x86-64.so.2 
#9 0x000000302aff79fa in _dl_open() from /lib64/tls/libc.so.6 
#10 0x000000302b201054 in dlopen_doit() from /lib64/libdl.so.2 
#11 0x000000302ad0aa60 in _dl_catch_error() from /lib64/ld-linux-x86-64.so.2 
#12 0x000000302b201552 in _dlerror_run() from /lib64/libdl.so.2 
#13 0x000000302b201092 in [email protected]@GLIBC_2.2.5() from /lib64/libdl.so.2 
#14 0x000000000041b559 in uap::meta::MetaManageServiceHandler::plugin_action this=0xb26000, [email protected], [email protected], [email protected], t=Variable "t" is not available.) 
at /usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/basic_string.h:1456 
#15 0x000000000041b0bc in uap::meta::MetaManageServiceHandler::plugin_action (this=0xb26000, [email protected], [email protected], [email protected], t=uap::meta::PluginActionType::RELOAD) 
at server/service_handler.cpp:173 
#16 0x0000000000417641 in uap::meta::test_Service_Handler_suite_test_case_manage_service_plugin_action_Test::TestBody (this=0xb16080) at test_load.cpp:73 
#17 0x00000000004446c6 in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0xb16080, method={__pfn = 0x21, __delta = 0}, location=0x537f30 "the test body") 
at ../../../../com/btest/gtest/src/gtest.cc:2744 
#18 0x000000000042dd1c in testing::Test::Run (this=0xb16080) at ../../../../com/btest/gtest/src/gtest.cc:2766 
#19 0x000000000042e8b4 in testing::TestInfo::Run (this=0xb17160) at ../../../../com/btest/gtest/src/gtest.cc:2958 
#20 0x000000000042f415 in testing::TestCase::Run (this=0xb23000, runtype=0) at ../../../../com/btest/gtest/src/gtest.cc:3160 
#21 0x0000000000436352 in testing::internal::UnitTestImpl::RunAllTests (this=0xb22000) at ../../../../com/btest/gtest/src/gtest.cc:5938 
#22 0x0000000000434299 in testing::UnitTest::Run (this=0x6f4220, run_type=0) at ../../../../com/btest/gtest/src/gtest.cc:5449 
#23 0x0000000000434268 in testing::UnitTest::Run (this=0x6f4220) at ../../../../com/btest/gtest/src/gtest.cc:5387 
#24 0x0000000000455404 in main (argc=1, argv=0x7fbffff8c8) at ../../../../com/btest/gtest/src/gtest_main.cc:38 

其實我已經重新定義了四種功能:

void __attribute__((constructor)) dlinit()                                         
{ 
} 

void __attribute__((destructor)) dldeinit() 
{ 
} 

void _init() 
{ 
} 

void _fini() 
{ 
} 
+0

什麼程序展示了這種行爲,用什麼插件?程序和插件是如何構建的?你的LD_LIBRARY_PATH變量是什麼?你的'plugin_path'是否包含'/'?它的價值是什麼?你應該在你的代碼之後添加一個'fflush(NULL)'! –

+0

感謝您的回覆,我只是沒有設置LD_LIBRARY_PATH和絕對路徑以/開頭的plugin_path,因爲我只是在這裏添加printf,但是我的代碼沒有,它不是fflush問題,因爲掛在dlopen – user2530422

+0

我不明白如何以及爲什麼你認爲代碼掛在'dlopen'時間?你使用了調試器嗎?顯示插件的代碼,以及程序的更多代碼。 –

回答

0

你應該gcc -Wall -g編譯兩個應用程序和插件,並使用調試器gdb(不要忘記也編譯插件源與-fPIC並鏈接其目標文件與-shared)。

正如你可能知道,dlopen -ing共享對象將運行具有功能constructorfunction attribute(還有如dlopen(3)說,過時_init功能)。此外,C++靜態數據的構造函數具有constructor屬性。

我想這些構造函數中的某些被某種方式阻塞(可能是輸入)。你也可以strace你的程序。

可能還有一些其他原因造成這種阻塞,例如, dlopen -ing從無響應的NFS服務器的NFS安裝的文件,等...

又見rtld-audit(7)ld.so(8)LD_DEBUG環境變量(嘗試將其設置爲all)。另外,在插件和程序上運行ldd

順便說一句,在你的代碼中缺少您的printf格式字符串終止換行符\n是可疑的(和不好的味道),你應該打印dlerror()dlopen失敗。至少在您的代碼後添加一個致電fflush(NULL);。會轉而代碼:

handle = dlopen(plugin_path.c_str(), RTLD_LAZY); 
if(!handle) { 
    printf("dlopening %s failed %s\n", plugin_path.c_str(), dlerror()); 
} else { 
    printf("dlopen %s success\n", plugin_path.c_str()); 
} 
fflush(NULL); 

您可能還損壞了堆(在程序的其它地方)到如此地步,dlopen(或你的插件)無法繼續工作。使用valgrind來查找內存損壞錯誤!

+0

是的,這些編譯和鏈接段已添加。並沒有_init _fini或安迪的構造函數。實際上,有時候插件會修改並更正,並且有時會掛起; – user2530422

+0

將gdb信息添加到線索 – user2530422

1

我想我找到了根本原因:在gdb信息中,掛起來自tcmalloc,我讀過tcmalloc相關的代碼和幾個鎖,然後我complie和鏈接,所以沒有tcmalloc,沒有任何反應,這會當tcmalloc工作時發現錯誤

+0

你知道掛鉤是什麼嗎?我正在加載一個dlopen庫,由於某種原因,它打開了第二個庫。在這個負載下tcmalloc是實時鎖定的。我也會看看源代碼,但是如果你已經發現了這個問題,那麼知道它會很棒。 – ChrisAshton84