2011-11-10 26 views
12

में ctypes के माध्यम से धागा स्थानीय भंडारण के साथ साझा लाइब्रेरी का उपयोग कर रहा अजगर में ctypes मॉड्यूल का उपयोग कर रहा एक साझा सी पुस्तकालय है, जो स्थानीय भंडारण थ्रेड शामिल लोड करने के लिए। यह एक लंबा इतिहास के साथ एक काफी बड़ी सी पुस्तकालय है, कि हम धागे को सुरक्षित बनाने की कोशिश कर रहे हैं। पुस्तकालय में बहुत से वैश्विक चर और स्थिरताएं हैं, इसलिए थ्रेड सुरक्षा की दिशा में हमारी प्रारंभिक रणनीति थ्रेड स्थानीय संग्रहण का उपयोग करना है। हम चाहते हैं कि हमारी लिबररी प्लेटफार्म स्वतंत्र हो, और Win32, win64 और 64-bit उबंटू दोनों पर थ्रेड सुरक्षा का संकलन और परीक्षण कर रहा है। एक शुद्ध सी प्रक्रिया से कोई समस्या नहीं प्रतीत होती है।मेमोरी रिसाव जब एक अजगर कार्यक्रम

हालांकि Win32 और उबंटू पर पायथन (2.6 और 2.7) में हम मेमोरी लीक देख रहे हैं। ऐसा लगता है कि एक पाइथन धागा समाप्त होने पर थ्रेड स्थानीय भंडारण ठीक से जारी नहीं किया जा रहा है। या कम से कम कि किसी भी तरह से अजगर प्रक्रिया "जागरूक" नहीं है कि स्मृति मुक्त हो गई है। एक ही समस्या भी वास्तव में Win32 पर एक ग # -program में देखा जाता है, लेकिन यह हमारे win64 सर्वर परीक्षण मशीन पर मौजूद नहीं है (चल अजगर 2.7 भी)।

समस्या इस तरह एक साधारण खिलौना उदाहरण के साथ reproduced किया जा सकता है:

एक सी फ़ाइल युक्त बनाएँ (linux/unix पर __declspec(dllexport) निकालने के लिए): खिड़कियों पर

#include <stdio.h> 
#include <stdlib.h> 
void __declspec(dllexport) Leaker(int tid){ 
    static __thread double leaky[1024]; 
    static __thread int init=0; 
    if (!init){ 
      printf("Thread %d initializing.", tid); 
      int i; 
      for (i=0;i<1024;i++) leaky[i]=i; 
      init=1;} 
    else 
     printf("This is thread: %d\n",tid); 
    return;} 

संकलित बुद्धि MINGW/लिनक्स पर जीसीसी जैसे:

gcc -o leaky.dll (या leaky.so) -shared the_file.c

,210

खिड़कियों पर हम दृश्य स्टूडियो के साथ संकलित किया जा सकता था, __declspec(thread) साथ __thread की जगह। हालांकि Win32 पर (अप winXP को मेरा मानना ​​है कि), यह अगर पुस्तकालय LoadLibrary साथ क्रम में लोड किया जा रहा है काम नहीं करता।

import threading, ctypes, sys, time 
NRUNS=1000 
KEEP_ALIVE=5 
REPEAT=2 
lib=ctypes.cdll.LoadLibrary("leaky.dll") 
lib.Leaker.argtypes=[ctypes.c_int] 
lib.Leaker.restype=None 
def UseLibrary(tid,repetitions): 
    for i in range(repetitions): 
     lib.Leaker(tid) 
     time.sleep(0.5) 
def main(): 
    finished_threads=0 
    while finished_threads<NRUNS: 
     if threading.activeCount()<KEEP_ALIVE: 
      finished_threads+=1 
      thread=threading.Thread(target=UseLibrary,args=(finished_threads,REPEAT)) 
      thread.start() 
    while threading.activeCount()>1: 
     print("Active threads: %i" %threading.activeCount()) 
     time.sleep(2) 
    return 
if __name__=="__main__": 
    sys.exit(main()) 

त्रुटि पुन: पेश करने के लिए पर्याप्त है कि:

अब की तरह एक अजगर कार्यक्रम बना सकते हैं। स्पष्ट रूप से कचरा कलेक्टर आयात करते हैं, जब से आपसे प्रत्येक नया थ्रेड मदद नहीं करता है एक collect gc.collect() कर।

थोड़ी देर के लिए मैंने सोचा कि समस्या को असंगत रनटाइम (विजुअल स्टूडियो के साथ संकलित पायथन, MINGW के साथ मेरी लाइब्रेरी) के साथ करना पड़ा था। लेकिन समस्या यह है Ubuntu पर नहीं, बल्कि एक win64 सर्वर पर भी है, पुस्तकालय MINGW साथ संकलित पार है, तब भी जब।

आशा है कि कोई भी मदद कर सके!

चीयर्स, साइमन कोक्केन्डोरफ, राष्ट्रीय सर्वेक्षण और डेनमार्क के कैडस्ट्रे।

+0

की समीक्षा करें जाना जाता अजगर कीड़े http://bugs.python.org/issue6627 http://bugs.python.org/issue3757 –

+0

आप सी में धागा पास पर अपने टपकाया चर मुक्त कर सकते हैं? इसे ठीक करने के लिए –

+0

, malloc का उपयोग करने का प्रयास करें और सरणी – pyCthon

उत्तर

3

ऐसा लगता है कि यह ctypes 'या पायथन की गलती नहीं है। मैं केवल उसी कोड को लिखकर, उसी दर पर लीक, उसी रिसाव को पुन: पेश कर सकता हूं।

अजीब तरह से, कम से कम उबंटू लिनक्स 64 पर, रिसाव तब होता है जब __thread चर के साथ लीकर() फ़ंक्शन को .so के रूप में संकलित किया जाता है और डलोपेन() के साथ प्रोग्राम से कहा जाता है। यह ठीक उसी कोड को चलाते समय नहीं होता है लेकिन नियमित रूप से सी प्रोग्राम के रूप में दोनों भागों को संकलित किया जाता है।

मुझे संदेह है कि गलती गतिशील रूप से जुड़े पुस्तकालयों और धागे-स्थानीय भंडारण के बीच कुछ बातचीत है। फिर भी, यह एक बदतर बग की तरह दिखता है (क्या यह वास्तव में अनियंत्रित है?)।

+0

शुरू करने से पहले एक थ्रेड पर setDaemon (True) सेट कर सकते हैं ऐसा लगता है कि यह धागा आपके सिद्धांत का बैक अप लेता है: http://sourceware.org/ml/libc-help/2011-04/msg00000.html –

+0

हाँ - और ऐसा लगता है कि ओएस निर्भर है। मुझे Win XP पर लाइब्रेरी लपेटना (लाइबोन या सी # द्वारा लाइब्रेरी को लपेटना, और मुझे लगता है कि आप सी से नोट करते हैं) (32 बिट), उबंटू (32 बिट और 64-बिट दोनों, मुझे विश्वास है) पर - हालांकि विंडोज सर्वर पर (64 बिट), मुझे यह नहीं दिख रहा है। – user1037171

1

मेरा अनुमान है कि धागे से जुड़ना समस्या नहीं है। एक धागा है कि joinable है (यानी, एक है कि अलग नहीं ), एक "ज़ोंबी सूत्र" का उत्पादन के साथ शामिल होने के लिए

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

आप धागा वस्तुओं .isAlive इकट्ठा करने और उपयोग करने के लिए अपने पाश को संशोधित करते हैं() और है कि पिछले जबकि पाश मुझे लगता है कि यह आपके स्मृति रिसाव का ध्यान रखना चाहिए में .join() उन पर।

+0

प्रारंभ करने और निकालने के लिए निःशुल्क अपने उत्तर के लिए धन्यवाद। मुझे लगता है कि धागे में शामिल नहीं होने की तरह समस्या है। यहां तक ​​कि अगर मैं सृजन के बाद हर धागे में शामिल हो जाता हूं, तो मुख्य धागे से अलग केवल एक धागा चल रहा है, समस्या बनी हुई है। मैं अपने डीएल में भी एक मुख्य समारोह (खिड़कियों के नीचे) के साथ पता लगा सकता हूं कि धागे डीएल से अलग हो जाते हैं। – user1037171

+0

वैकल्पिक रूप से आप –

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