2008-09-20 8 views
9

निम्न प्रोग्राम बहुत आसान है: यह प्रत्येक आधे सेकेंड में एक सिंगल डॉट आउटपुट करता है। यदि यह SIGQUIT प्राप्त करता है, तो यह 10 क्यू एस आउटपुट तक पहुंच जाता है। यह प्राप्त करता है, तो एक SIGTSTP(Ctrl - जेड), यह दस जेड रों आउटपुट।पायथन सिग्नल की समस्याएं: सिग्क्विट हैंडलर निष्पादन में देरी करता है अगर सिग्क्विट किसी अन्य सिग्नल हैंडलर के निष्पादन के दौरान प्राप्त होता है?

यदि यह प्राप्त करता है एक SIGTSTP जबकि मुद्रण क्यू रों, यह दस जेड प्रिंट होगा रों के बाद यह दस क्यू के साथ किया है। यह एक अच्छी बात है।

हालांकि, अगर यह एक SIGQUIT प्राप्त करता प्रिंट करते समय जेड रों, यह उन्हें बाद क्यू मुद्रित करने के लिए रों विफल रहता है। इसके बजाए, जब मैं मैन्युअल रूप से कीबोर्ड इंटरप्ट के माध्यम से निष्पादन को समाप्त कर देता हूं तो यह उन्हें प्रिंट करता है। मैं क्यू एस जेड एस के तुरंत बाद मुद्रित करना चाहता हूं।

यह Python2.3 का उपयोग होता है।

मैं क्या गलत कर रहा हूं? मुचस gracias।

#!/usr/bin/python 

from signal import * 
from time import sleep 
from sys import stdout 

def write(text): 
    stdout.write(text) 
    stdout.flush() 

def process_quit(signum, frame): 
    for i in range(10): 
     write("Q") 
     sleep(0.5) 

def process_tstp(signum, frame): 
    for i in range(10): 
     write("Z") 
     sleep(0.5) 

signal(SIGQUIT, process_quit) 
signal(SIGTSTP, process_tstp) 

while 1: 
    write('.') 
    sleep(0.5) 

उत्तर

6

आपकी बड़ी समस्या सिग्नल हैंडलर में अवरुद्ध हो रही है।

यह आमतौर पर निराश होता है क्योंकि इससे अजीब समय की स्थिति हो सकती है। लेकिन यह आपकी समस्या का कारण नहीं है क्योंकि सिग्नल हैंडलर की आपकी पसंद के कारण समय की स्थिति आप मौजूद हैं।

वैसे भी, यहां कम से कम समय की स्थिति को कम करने के लिए कैसे करें अपने हैंडलर में झंडे सेट करके और वास्तविक कार्य करने के लिए लूप को मुख्य छोड़कर। कोड के बाद आपका कोड अजीब तरीके से व्यवहार क्यों कर रहा है इसका स्पष्टीकरण दिया गया है।

#!/usr/bin/python 

from signal import * 
from time import sleep 
from sys import stdout 

print_Qs = 0 
print_Zs = 0 

def write(text): 
    stdout.write(text) 
    stdout.flush() 

def process_quit(signum, frame): 
    global print_Qs 
    print_Qs = 10 

def process_tstp(signum, frame): 
    global print_Zs 
    print_Zs = 10 

signal(SIGQUIT, process_quit) 
signal(SIGTSTP, process_tstp) 

while 1: 
    if print_Zs: 
     print_Zs -= 1 
     c = 'Z' 
    elif print_Qs: 
     print_Qs -= 1 
     c = 'Q' 
    else: 
     c = '.' 
    write(c) 
    sleep(0.5) 

वैसे भी, यहां क्या हो रहा है।

SIGTSTP सिग्क्विट से अधिक विशेष है।

SIGTSTP अन्य संकेतों को वितरित होने से मास्क करता है जबकि सिग्नल हैंडलर चल रहा है। जब कर्नेल SIGQUIT को वितरित करने के लिए जाता है और देखता है कि SIGTSTP का हैंडलर अभी भी चल रहा है, तो यह बस बाद में इसे बचाता है। एक बार एक और सिग्नल डिलीवरी के लिए आता है, जैसे कि CTRL + सी (उर्फ कीबोर्ड इंटरप्ट), कर्नेल याद करता है कि यह कभी सिग्क्विट नहीं पहुंचाता और इसे अब वितरित करता है।

यदि आप मुख्य पाश में को while 1: बदल सकते हैं और अपने परीक्षण का मामला फिर से आप देखेंगे, कार्यक्रम SIGTSTP हैंडलर चल के बाद से बाहर निकलने के लिए फिर से ट्रिगर नहीं है कर्नेल के संकेत वितरण प्रणाली के बिना बाहर निकल जाएगा।

गुड लक!

1

लिनक्स 2.6 पर पायथन 2.5.2 पर।24, आपका कोड ठीक वैसे ही काम करता है जब आप अपने वांछित परिणामों का वर्णन करते हैं (यदि पिछले सिग्नल को प्रोसेस करते समय सिग्नल प्राप्त होता है, तो पहले सिग्नल समाप्त होने के तुरंत बाद नया सिग्नल संसाधित होता है)।

लिनक्स 2.6.16 पर पायथन 2.4.4 पर, मुझे आपके द्वारा वर्णित समस्या व्यवहार दिखाई देता है।

मुझे नहीं पता कि यह पायथन या लिनक्स कर्नेल में बदलाव के कारण है या नहीं।

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