2012-01-25 10 views
6

समस्याएं होती हैं, तो समस्याएं होती हैं, अगर समस्याएं होती हैं: मैथवर्क समर्थन के साथ कुछ चर्चाओं के बाद, यह एक संघर्ष साबित हुआ सिस्टम बूस्ट और मैटलैब के भेजे गए बूस्ट लाइब्रेरीज़ के बीच: जब मैंने सिस्टम बूस्ट हेडर के साथ संकलित किया और मैटलैब बूस्ट लाइब्रेरीज़ (पुराने) मैटलब बूस्ट लाइब्रेरी से जुड़े, तो यह सीगफॉल्ट हो गया। जब मैंने सिस्टम बूस्ट के साथ संकलित और गतिशील रूप से जुड़ा हुआ था, लेकिन फिर यह गतिशील रूप से मैटलैब बूस्ट पुस्तकालयों को लोड करता था, यह हमेशा के लिए लटका हुआ था।मैटलैब से बूस्ट :: थ्रेड का उपयोग करते समय लटकाएं और/या segfault, जब सीधे

सिस्टम बूस्ट कार्यों के लिए स्टेटिक लिंकिंग, जैसा कि मैटलैब जहाजों के साथ चिपकने और संकलित करने के बढ़ावा के लिए सही शीर्षलेख डाउनलोड करता है। बेशक, मैकबैब के मैक का निर्माण उनके फ़ाइल नामों में संस्करण संख्या नहीं है, हालांकि लिनक्स और माना जाता है कि विंडोज़ करता है। संदर्भ के लिए R2011b बूस्ट 1.44 का उपयोग करता है।


मैं कुछ बहु कोड है कि ठीक काम करता है जब यह सीधे संकलित है है, लेकिन segfaults और/या गतिरोध जब यह एक मैटलैब mex इंटरफ़ेस से कहा जाता है। मुझे नहीं पता कि अलग-अलग वातावरण मेरे कोड में एक दोष दिखा रहा है, या क्या, लेकिन मैं इसे समझ नहीं सकता ....

मैं इसे तीन मशीन कॉन्फ़िगरेशन पर चला रहा हूं (हालांकि कई हैं CentOS बक्से के):

  • OSX 10.7, जी ++ 4.2, को बढ़ावा देने के 1.48, मैटलैब R2011a (बजना ++ 2.1 भी स्टैंडअलोन के लिए काम करता है,
  • प्राचीन CentOS बजना उपयोग करने के लिए) MEX प्राप्त करने की कोशिश नहीं की है, जी ++ 4.1 .2, 1.33.1 को बढ़ावा दें (डीबग करें और डीबग न करें), मैटलैब आर 2010 बी
  • प्राचीन सेंटोस, जी ++ 4.1.2, 1.40 बढ़ाएं (कोई डीबग संस्करण स्थापित नहीं है), मैटलैब आर 2010 बी

यहां इस व्यवहार के साथ एक पारे हुए संस्करण है।

#include <queue> 
#include <vector> 

#include <boost/thread.hpp> 
#include <boost/utility.hpp> 

#ifndef NO_MEX 
#include "mex.h" 
#endif 

class Worker : boost::noncopyable { 
    boost::mutex &jobs_mutex; 
    std::queue<size_t> &jobs; 

    boost::mutex &results_mutex; 
    std::vector<double> &results; 

    public: 

    Worker(boost::mutex &jobs_mutex, std::queue<size_t> &jobs, 
      boost::mutex &results_mutex, std::vector<double> &results) 
     : 
      jobs_mutex(jobs_mutex), jobs(jobs), 
      results_mutex(results_mutex), results(results) 
    {} 

    void operator()() { 
     size_t i; 
     float r; 

     while (true) { 
      // get a job 
      { 
       boost::mutex::scoped_lock lk(jobs_mutex); 
       if (jobs.size() == 0) 
        return; 

       i = jobs.front(); 
       jobs.pop(); 
      } 

      // do some "work" 
      r = rand()/315.612; 

      // write the results 
      { 
       boost::mutex::scoped_lock lk(results_mutex); 
       results[i] = r; 
      } 
     } 
    } 
}; 

std::vector<double> doWork(size_t n) { 
    std::vector<double> results; 
    results.resize(n); 

    boost::mutex jobs_mutex, results_mutex; 

    std::queue<size_t> jobs; 
    for (size_t i = 0; i < n; i++) 
     jobs.push(i); 

    Worker w1(jobs_mutex, jobs, results_mutex, results); 
    boost::thread t1(boost::ref(w1)); 

    Worker w2(jobs_mutex, jobs, results_mutex, results); 
    boost::thread t2(boost::ref(w2)); 

    t1.join(); 
    t2.join(); 

    return results; 
} 

#ifdef NO_MEX 
int main() { 
#else 
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs) { 
#endif 
    std::vector<double> results = doWork(10); 
    for (size_t i = 0; i < results.size(); i++) 
     printf("%g ", results[i]); 
    printf("\n"); 
} 

ध्यान दें कि बढ़ावा 1.48 पर, मैं एक ही व्यवहार करता है, तो मैं एक मानक समारोह में functor बदल सकते हैं और सिर्फ boost::thread करने के लिए अतिरिक्त तर्कों के रूप mutexes/आंकड़ों के boost::ref रों पारित मिलता है। बूस्ट 1.33.1 हालांकि इसका समर्थन नहीं करता है।


जब मैं इसे सीधे संकलन, यह हमेशा ठीक चलाता है - मैं कभी नहीं देखा है यह किसी भी स्थिति में असफल:

$ g++ -o testing testing.cpp -lboost_thread-mt -DNO_MEX 
$ ./testing 
53.2521 895008 5.14128e+06 3.12074e+06 3.62505e+06 1.48984e+06 320100 4.61912e+06 4.62206e+06 6.35983e+06 

मैटलैब से चल रहा है, मैं एक बहुत देखा है कोड में अलग-अलग बदलाव करने के बाद विभिन्न व्यवहारों के बारे में और फिर भी, हालांकि कोई बदलाव नहीं जो वास्तव में मुझे कोई समझ में आता है। लेकिन यहाँ क्या मैं ऊपर सटीक कोड के साथ देखा गया है:

  • पर OSX/बढ़ावा 1.48:
    • यह एक रिलीज-संस्करण को बढ़ावा देने से लिंक किया गया है, मैं एक segfault एक लगभग 0 तक पहुंच की कोशिश boost::thread::start_thread के अंदर पता, t1 के कन्स्ट्रक्टर से बुलाया जा रहा है।
    • यदि यह डीबग-वेरिएंट बूस्ट से जुड़ा हुआ है, तो यह पहले boost::thread::join में हमेशा के लिए लटकता है। मैं पूरी तरह से निश्चित नहीं हूं, लेकिन मुझे लगता है कि कार्यकर्ता धागे वास्तव में इस बिंदु पर पूरा हो गए हैं (info threads में कुछ भी न देखें जो स्पष्ट रूप से उन्हें है)।
  • CentOS/बढ़ावा 1.33.1 और 1.40 पर:
      रिहाई को बढ़ावा देने के साथ
    • , मैं pthread_mutex_lock में एक segfault मिलता है, t1 पर boost::thread::join से बुलाया जा रहा है।
    • डिबगिंग बूस्ट के साथ, यहमें pthread_mutex_lock के अंदर एक ही स्थान पर हमेशा के लिए लटकता है। जैसा कि नीचे दिखाया गया है, कार्यकर्ता धागे इस बिंदु पर पूरा हो गए हैं।

मैं कुछ भी segfaults साथ बहुत कुछ करने के लिए कैसे, क्योंकि वे कभी नहीं हो जब मैं डिबगिंग प्रतीकों है कि वास्तव में मुझे बता सकते हैं क्या नल पॉइंटर है पता नहीं है।

मटरगश्ती हमेशा के मामले में, मैं अगर मैं GDB में के माध्यम से आगे बढ़ रहा हूँ हमेशा कुछ इस तरह प्राप्त करने के लिए लग रहे हैं: दोनों धागे की तरह लगती है t1.join() को कॉल करने से पहले पूरी हो

99  Worker w1(jobs_mutex, jobs, results_mutex, results); 
(gdb) 
100  boost::thread t1(boost::ref(w1)); 
(gdb) 
[New Thread 0x47814940 (LWP 19390)] 
102  Worker w2(jobs_mutex, jobs, results_mutex, results); 
(gdb) 
103  boost::thread t2(boost::ref(w2)); 
(gdb) 
[Thread 0x47814940 (LWP 19390) exited] 
[New Thread 0x48215940 (LWP 19391)] 
[Thread 0x48215940 (LWP 19391) exited] 
105  t1.join(); 

है। तो मैंने ताले के बीच "काम करने" अनुभाग में sleep(1) कॉल जोड़ने का प्रयास किया; जब मैं के माध्यम से आगे बढ़ रहा हूँ, t1.join() करने के लिए कॉल के बाद धागे से बाहर निकलें और यह अभी भी हमेशा के लिए लटका हुआ है:

106  t1.join(); 
(gdb) 
[Thread 0x47814940 (LWP 20255) exited] 
[Thread 0x48215940 (LWP 20256) exited] 
# still hanging 

मैं updoWork कार्य करने के लिए बाहर, results एक ही परिणाम के साथ से भर जाता है तो उस पर स्टैंडअलोन संस्करण प्रिंट यह मशीन, तो ऐसा लगता है कि यह सब कुछ हो रहा है।

मुझे नहीं पता कि सीजीफाल्ट या पागल लटकने वाली नस्ल के कारण क्या हो रहा है, या ऐसा क्यों है कि यह हमेशा मैटलैब के बाहर काम करता है और अंदर कभी नहीं, या यह डिबगिंग प्रतीकों के साथ/बिना अलग क्यों है, और मुझे नहीं पता इसे समझने में कैसे आगे बढ़ें। कोई विचार?


@ alanxz के सुझाव पर, मैं valgrind के Memcheck, helgrind, और DRD उपकरण के तहत कोड का स्टैंडअलोन संस्करण हुई:

  • valgrind 3.5 का उपयोग कर CentOS पर, उपकरण में से कोई भी किसी भी देना गैर दबाए गए त्रुटियां।
  • ओएसएक्स पर valgrind का उपयोग 3.7:
    • मेमचेक कोई भी गैर-दबाने वाली त्रुटियां नहीं देता है।
    • ओएसएक्स पर किसी भी बाइनरी (उदा। valgrind --tool=helgrind ls सहित) पर चलने पर हेल्ग्रिंड क्रैश हो जाता है, जो असमर्थित निर्देश के बारे में शिकायत करता है।
    • डीआरडी सौ से अधिक त्रुटियों देता है।

DRD त्रुटियाँ सुंदर मेरे लिए गूढ़ हैं, और हालांकि मैं मैनुअल और इतने पर पढ़ा है, मैं उनमें से कोई मतलब नहीं कर सकते हैं। यहाँ पहले एक है, कोड, जहां मैं बाहर दूसरे कार्यकर्ता/धागा टिप्पणी की के एक संस्करण पर:

Thread 2: 
Conflicting load by thread 2 at 0x0004b518 size 8 
    at 0x3B837: void boost::call_once<void (*)()>(boost::once_flag&, void (*)()) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x2BCD4: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x2BA62: thread_proxy (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x2D88BE: _pthread_start (in /usr/lib/system/libsystem_c.dylib) 
    by 0x2DBB74: thread_start (in /usr/lib/system/libsystem_c.dylib) 
Allocation context: Data section of r/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib 
Other segment start (thread 1) 
    at 0x41B4DE: __bsdthread_create (in /usr/lib/system/libsystem_kernel.dylib) 
    by 0x2B959: boost::thread::start_thread() (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x100001B54: boost::thread::thread<boost::reference_wrapper<Worker> >(boost::reference_wrapper<Worker>, boost::disable_if<boost::is_convertible<boost::reference_wrapper<Worker>&, boost::detail::thread_move_t<boost::reference_wrapper<Worker> > >, boost::thread::dummy*>::type) (thread.hpp:204) 
    by 0x100001434: boost::thread::thread<boost::reference_wrapper<Worker> >(boost::reference_wrapper<Worker>, boost::disable_if<boost::is_convertible<boost::reference_wrapper<Worker>&, boost::detail::thread_move_t<boost::reference_wrapper<Worker> > >, boost::thread::dummy*>::type) (thread.hpp:201) 
    by 0x100000B50: doWork(unsigned long) (testing.cpp:66) 
    by 0x100000CE1: main (testing.cpp:82) 
Other segment end (thread 1) 
    at 0x41BBCA: __psynch_cvwait (in /usr/lib/system/libsystem_kernel.dylib) 
    by 0x3C0C3: boost::condition_variable::wait(boost::unique_lock<boost::mutex>&) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x2D28A: boost::thread::join() (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib) 
    by 0x100000B61: doWork(unsigned long) (testing.cpp:72) 
    by 0x100000CE1: main (testing.cpp:82) 

लाइन 66 धागे के निर्माण है, और 72 join कॉल है, बीच में टिप्पणी के अलावा कुछ भी नहीं है। जहां तक ​​मैं कह सकता हूं, यह कह रहा है कि मास्टर थ्रेड के उस हिस्से और कार्यकर्ता थ्रेड के प्रारंभिकरण के बीच एक दौड़ है ...लेकिन मैं वास्तव में समझ में नहीं आता कि यह कैसे संभव है?

डीआरडी is here से बाकी उत्पादन; मुझे इससे कुछ भी नहीं मिल रहा है।

+1

क्या आपने इसे वालग्रिंड के तहत चलाने की कोशिश की है, [हेल्ग्रिंड] (http://valgrind.org/docs/manual/hg-manual.html), या [DRD] (http://valgrind.org/docs/manual /drd-manual.html)? इससे क्या हो रहा है इसके बारे में कुछ संकेत बता सकते हैं। – alanxz

+0

@alanxz सुझाव के लिए धन्यवाद, मुझे हेल्ग्रिंड/डीआरडी के बारे में पता नहीं था। मैंने सवाल के बारे में कुछ कहने के बारे में कुछ विवरण जोड़ा है। मुझे ओएसएक्स पर डीआरडी त्रुटियां मिलती हैं, लेकिन मैन्युअल पढ़ने के बावजूद उनका क्या मतलब है, इसका कोई मतलब नहीं है .... – Dougal

+0

क्या कोई भी पर्यावरण जैसे लिनक्स पर @rpath सेट अप करने का प्रयास करता है? मेरे पास वर्तमान में एक ही समस्या है, मैं सोच रहा हूं कि मेक्सिको को अपनी निर्भरताओं के उचित अलगाव करना चाहिए। – Raffi

उत्तर

1

क्या आप वाकई सबसे सरल मामला है जो segfaults और/या लटकता है? यदि डीआरडी के नतीजे थ्रेड निर्माण और जुड़ने के बीच दौड़ की स्थिति को इंगित करते हैं, तो ऐसा लगता है कि आपका कोड गलती नहीं हो सकता है (विशेष रूप से जब आप वास्तव में mex-विशिष्ट सुविधाओं का उपयोग नहीं करते हैं, लेकिन बस mex के तहत चल रहा है बग ट्रिगर करता है)। - यदि ऐसा है तो यह होता है, यह अपने बग नहीं है, और यदि ऐसा नहीं होता है, शायद

#include <boost/thread.hpp> 

void doNothing() { return; } 

void doWork() { 
    boost::thread t1(doNothing); 
    t1.join(); 
} 

#ifdef NO_MEX 
int main() { 
#else 
#include "mex.h" 
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs) { 
#endif 
    doWork(); 
} 

यह निश्चित रूप से SEGFAULT चाहिए नहीं या तो mex तहत लटका या सीधे संकलित:

हो सकता है कि सिर्फ इस संस्करण की कोशिश आप अपने संस्करण के बीच की दूरी को प्रगतिशील रूप से बंद कर सकते हैं और यह बग-कारण जोड़ को ढूंढने के लिए कर सकते हैं।

+0

हाँ, वह संस्करण segfaults भी। मुझे लगता है कि मैक्स और बूस्ट थ्रेड बस एक साथ काम नहीं करते हैं। इसे बग और पोर्ट के रूप में रिपोर्ट करने का समय pthreads, मुझे लगता है .... – Dougal

0

अपने कोड में असफलता का एक बिंदु है: किसी भी धागा अधिक से अधिक 2 सेकंड की देरी की जाती है, ताला निर्माता में timed_lock कॉल टाइम आउट कर सकते हैं, म्युटेक्स नहीं हासिल कर ली है, और आप संरक्षित संरचना का उपयोग वैसे भी। यदि आप टाइम म्यूटेक्स का उपयोग करते हैं, तो आपको यह जांचना होगा कि लॉक ने वास्तव में म्यूटेक्स को लॉक किया है या केवल समय समाप्त कर दिया है या नहीं। यह ताले 'owns_lock() विधि को कॉल करके चेक किया जा सकता है।

मुझे समय के म्यूटेक्स के लिए कोई प्रेरणा नहीं दिखाई देती है, और आप "टाइम थ्रेड स्टफ लेने के बाद" का जिक्र करते हैं, लेकिन मुझे अभी भी इस म्यूटेक्स टाइमआउट बग को गलती होने पर संदेह है। क्या यह बग तब भी होता है जब आप सादे mutex के साथ timed_mutex को प्रतिस्थापित करते हैं?

+0

मैंने मूल रूप से सादा 'mutex' का उपयोग किया; डेडलॉक व्यवहार को देखने के बाद 'timed_mutex' सामान जोड़ा गया था। किसी कारण से मैंने सोचा कि 'timed_mutex' ने अपवाद फेंक दिया है अगर उसने लॉक हासिल नहीं किया है, हालांकि मुझे लगता है कि मुझे नहीं पता कि मैंने ऐसा क्यों सोचा। इसके अलावा, जब यह segfaults, यह तुरंत होता है - निश्चित रूप से कुछ नहीं जो 2 सेकंड के बाद हो रहा है। – Dougal

+0

स्पष्ट होने के लिए: हाँ, जब भी मैं 'timed_mutex' को सादा' mutex' के साथ प्रतिस्थापित करता हूं (और समय तर्क और इसलिए स्पष्ट रूप से) को प्रतिस्थापित करता हूं, तब भी मुझे segfaults/hangs मिलते हैं। अब मैं अपने ओएसएक्स बूस्ट 1.48 मशीन और सेंटोस बूस्ट 1.33.1 मशीन के बीच की समस्या में एक स्थिरता देख रहा हूं जो मुझे पहले नहीं लग रहा था, हालांकि ... थोड़ा और अच्छी तरह से जांच करेगा और फिर सवाल संपादित करेगा । – Dougal

+0

मैंने उस समस्या को ठीक कर लिया है और सवाल संपादित किया है। ऐसा लगता है कि ताला सामान समस्या नहीं थी, क्योंकि यह ओएसएक्स + नए बूस्ट पर होने से पहले सेगफाल्ट करता है, और सेंटोस + बूढ़े बूढ़ों को सफलतापूर्वक पूरा करता है (कम से कम जब मैं उन्हें डिबग कर रहा हूं) लेकिन या तो क्रैश या लटका जब शामिल होने के लिए कहा। – Dougal

संबंधित मुद्दे