2012-12-26 9 views
11

नहीं करना चाहिए, मैं मिनी-शैल लिख रहा हूं (नहीं, स्कूल के लिए नहीं: पी; अपने स्वयं के आनंद के लिए) और अधिकांश बुनियादी कार्यक्षमता अब की गई है लेकिन मैं SIGTSTP को संभालने का प्रयास करते समय अटक गया हूं।वेटपिड अवरुद्ध करना जब इसे

माना जाता है कि जब कोई उपयोगकर्ता Ctrl+Z दबाता है, तो SIGTSTP को खोल की अग्रभूमि प्रक्रिया में भेजा जाना चाहिए, और शैल सामान्य रूप से जारी रखना चाहिए।

प्रत्येक प्रक्रिया बनाने (अगर यह एक अग्रभूमि प्रक्रिया है) के बाद, निम्न कोड इंतजार कर रहा है:

if(waitpid(pid, &processReturnStatus, WUNTRACED)>0){//wait stopped too 
    if(WIFEXITED(processReturnStatus) || WIFSIGNALED(processReturnStatus)) 
     removeFromJobList(pid); 
} 

और मैं संकेत से निपटने कर रहा हूँ इस प्रकार है:

void sigtstpHandler(int signum) 
{ 
    signum++;//Just to remove gcc's warning 
    pid_t pid = findForegroundProcessID(); 
    if(pid > -1){ 
     kill(-pid, SIGTSTP);//Sending to the whole group 
    } 
} 

क्या होता है जब मैं Ctrl+Z दबाता हूं, तो प्रक्रिया की स्थिति को देखने के लिए बच्चे की प्रक्रिया वास्तव में निलंबित हो जाती है (ps -all का उपयोग करके) लेकिन मेरा खोल waitpid पर लटका हुआ है आर रिटर्न देता है भले ही मैंने WUNTRACED फ्लैग पास किया, जहां तक ​​मुझे समझा जाता है कि प्रक्रिया को बंद होने पर waitpid वापस करना है।
तो मैं गलत क्या कर सकता था? या क्या मैं वेटपीड के व्यवहार को गलत तरीके से समझता हूं?

नोट्स:
-findForegroundProcessID() सही पिड देता है; मैंने दोबारा जांच की।
मैं प्रत्येक प्रक्रिया के समूह को बदलने हूँ जब सही होने के बाद मैं fork
-Handling Ctrl+C ठीक काम कर रहा है
-अगर मैं एक टर्मिनल का उपयोग मेरी खोल रुक जाता है के बाद SIGCONT भेजने के लिए, बच्चे प्रक्रिया अपना काम शुरू और खोल यह काटनेवाला अंत में।
- मैं SIGTSTP को पकड़ रहा हूं जहां तक ​​मैंने पढ़ा (और परीक्षण) पकड़ा जा सकता है। - मैंने वेटपिड के बजाय वेटिड का उपयोग करने की कोशिश की, अगर समस्या बनी रहती है। संपादित करें:

void sigchldHandler(int signum) 
{ 
    signum++;//Just to remove the warning 
    pid_t pid; 
    while((pid = waitpid(-1, &processReturnStatus, 0)) > 0){  
     removeFromJobList(pid); 
    } 
    if(errno != ECHILD) 
     unixError("kill error"); 
} 

मेरे SIGCHLD हैंडलर।

+0

IIUC, आप SIGSTP को पकड़ने की कोशिश कर रहे हैं। आप सिगस्ट या सिगकिल नहीं पकड़ सकते हैं। – wildplasser

+1

मुझे यकीन नहीं है कि सिगस्टॉप एसआईजीएसटीपी जैसा ही है लेकिन एक पुस्तक के मुताबिक, सिगस्टॉप पकड़ा नहीं जा सकता है लेकिन सिगस्टॉप कर सकता है, असल में मुझे यकीन है कि मैंने इसे पकड़ा क्योंकि मैंने टेस्ट – Fingolfin

+0

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

उत्तर

1

SIGCHLD रुकने वाले बच्चों के लिए डिलीवर किया गया है। waitpid() सिग्नल हैंडलर में पर कॉल करें - जो WUNTRACED निर्दिष्ट नहीं करता है - हमेशा के लिए ब्लॉक करता है।

शायद आपके पास removeFromJobList() दो अलग-अलग स्थानों में प्रसंस्करण नहीं होना चाहिए। अगर मुझे लगता है, ऐसा लगता है कि यह वैश्विक डेटा संरचनाओं को छूता है, और सिग्नल हैंडलर में नहीं है।

+0

मुझे सिगचल के बारे में और अधिक पढ़ना चाहिए था, वास्तव में इसे पकड़ने का इंतजार था, यह प्रक्रिया में इंतजार नहीं था क्रिएशन बी सिग्नल हैंडलर। बहुत बहुत धन्यवाद =) – Fingolfin

1

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

एकमात्र सिग्नल जिसे आप पकड़ना चाहते हैं वह सिग्लड है। कारण यह है कि यदि आपकी प्रक्रियाओं को ठीक से फोर्क किया जाता है, तो कर्नेल उस सिग्नल को अग्रभूमि प्रक्रिया में भेज देगा और यह इसे समाप्त कर देगा या इसे रोक देगा या जो कुछ भी सिग्नल ठीक से करेगा।

जब प्रक्रिया समूह सही तरीके से सेट नहीं होते हैं, तो संकेत गलत प्रक्रिया में भेजे जाएंगे। इसका परीक्षण करने का एक तरीका अग्रभूमि प्रक्रिया चलाकर और Ctrl-Z को मारना है।यदि आपका पूरा खोल मौजूद है, तो Ctrl-Z सिग्नल पूरे खोल में भेजा जा रहा है। इसका मतलब है कि आपने नई प्रक्रिया को नए प्रक्रिया समूह में सेट नहीं किया है और इसे टर्मिनल दिया है।

अब यह है कि आपको क्या करना है यदि आपका Ctrl-Z सिग्नल आपके पूरे खोल को रोक रहा है। एक बार जब आप प्रक्रिया को फोर्क करते हैं, तो बच्चे की प्रक्रिया में: - सेटजीडिड का उपयोग करके प्रक्रिया को अपने समूह में सेट करें। - इसे सिगेटू को अवरुद्ध करके और इसे tcsetpgrp का उपयोग करके टर्मिनल देकर एक सेने टर्मिनल दें।

अभिभावक में: - सेटजीड का उपयोग करके अपने बच्चे की प्रक्रिया भी सेट करें। ऐसा इसलिए है क्योंकि आपको कोई जानकारी नहीं है कि क्या बच्चा या माता-पिता पहले निष्पादित करेंगे, इसलिए यह दौड़ की स्थिति से बचाता है। यह दो बार सेट करने के लिए चोट नहीं है।

+0

उत्तर के लिए धन्यवाद, मैं एक सिग्ल्ड हनल्डर स्थापित कर रहा हूं (इसलिए Ctrl + C को ठीक से क्यों काम करना ठीक है)। यह थोड़ा अजीब लगता है, आप कह रहे हैं कि सिग्नल को संभालने वाला एकमात्र संकेत है जिसे मैं संभालना चाहता हूं? लेकिन मुझे SIGCHLD नहीं मिलता है जब एक बच्चे को सिग्स्टस्ट सिग्नल प्राप्त होता है लेकिन मुझे लगता है कि मैं समझ सकता हूं कि आपका क्या मतलब है। विचार यह है कि एक नई प्रक्रिया को अपना टर्मिनल दें और इसे अग्रभूमि बनाएं ताकि जब Ctrl + Z चला जाए, तो यह केवल अग्रभूमि प्रक्रिया को हिट करता है, न कि मेरे खोल को Ctrl + Z को पूरी तरह से संभाले बिना? – Fingolfin

+0

मैं अपना सिग्नल हैंडलर सेट कर रहा हूं, जैसा कि मैंने पहले ही ऊपर बताया है, और मैंने पुष्टि की है कि अब बच्चे की प्रक्रिया सिग्नल प्राप्त कर रही है और इसे रोक दिया जा रहा है लेकिन प्रतीक्षा अभी भी वापस नहीं आ रही है। – Fingolfin

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