2013-07-11 6 views
5

मेरे पास एक सी ++ प्रोग्राम है जो दूसरों पर निगरानी रखता है। अगर यह पता चलता है कि एक प्रक्रिया अब नहीं चल रही है, तो यह system के माध्यम से इसे पुनरारंभ करता है। समस्या यह है कि, अगर मैं वॉचडॉग प्रक्रिया को मारता हूं, तो जिस प्रक्रिया को शुरू किया गया है वह भी मर जाता है।बाल प्रक्रियाओं को कैसे बढ़ाया जाए जो माता-पिता के साथ मर नहीं जाते?

void* ProcessWatchdog::worker(void* arg) 
{ 
    //Check if process is running 
    if(!processRunning) 
     system("processName /path/to/processConfig.xml &"); 
} 

नई बाल प्रक्रिया सही ढंग से शुरू हो जाती है, और बिना किसी समस्या के चलती है। लेकिन जब माता-पिता (अब यह ProcessWatchdog प्रक्रिया) मर जाता है, तो बच्चा भी मर जाता है। मैं एक बच्चे की प्रक्रिया कैसे उत्पन्न कर सकता हूं जो माता-पिता से पूरी तरह से स्वतंत्र है?

मैंने pclose और popen, प्रक्रिया शुरू करने वाली शैल स्क्रिप्ट चलाने और कुछ अन्य रणनीतियों का उपयोग करने का प्रयास किया है, लेकिन इसका कोई फायदा नहीं हुआ है। मैं बाल प्रक्रियाओं में SIGHUP संकेतों को अनदेखा कर रहा हूं, लेकिन वे अभी भी मर जाते हैं।

तो आदर्श रूप में, मैं सिस्टम को ऐसी प्रक्रिया शुरू करने के लिए कहूंगा जो पूरी तरह से माता-पिता से स्वतंत्र है। मैं बच्चे के साथ समाप्त होने के लिए बच्चे के trace चाहता हूं, और इसके लिए/सिस्टम को यह नहीं पता कि ProcessWatchdog इसे पहले स्थान पर शुरू कर दिया है।

क्या ऐसा कोई तरीका है जिससे मैं ऐसा कर सकता हूं?

मैं इसे लिनक्स पर सी ++ में लिख रहा हूं।

+0

संभावित डुप्लिकेट [सिस्टम के साथ उत्पन्न होने वाली बाल प्रक्रिया() को माता-पिता को मारने के सिग्नल और निकास के बाद चलते रहें] (http://stackoverflow.com/questions/12945189/make-child- प्रक्रिया-स्पॉन्डेड-साथ-सिस्टम-रख-चलने-बाद-माता-पिता-हो-मार-सिग) –

+0

मुझे नहीं लगता कि सिस्टम का उपयोग करना एक अच्छा विचार है .... – Alexis

+0

सिस्टम का उपयोग क्यों नहीं करना एक अच्छा विचार है? स्पष्ट सुरक्षा मुद्दों के अलावा? मैं इसे एक बहुत ही नियंत्रित वातावरण में एक एम्बेडेड सिस्टम पर कर रहा हूं, और मैं गलत सिस्टम कॉल के बारे में चिंतित नहीं हूं। क्या कोई और कारण है कि मुझे सावधान रहना चाहिए? सुरक्षा समस्याओं के लिए –

उत्तर

0

प्रक्रिया नाम से पहले setsid साथ system का उपयोग करें।

system("setsid processname /path/to/processConfig.xml &"); 

यह कार्यक्रम को एक नए सत्र में लॉन्च करेगा।

3

system(...) का उपयोग न करें यह बहु-थ्रेडिंग सुरक्षित नहीं है।

int pid = fork(); 

if(pid==0) 
{ 
    int rc = execv("processname", "/path/to/processConfig.xml &"); 
    if(rc == -1) 
    { 
    printf(stderr, "processname failed to start. %d", errno); 
    } 
    ... 
} 
else 
{ 
    //continue with the parent 
} 
+3

क्या आप 'मल्टी-थ्रेडिंग सुरक्षित नहीं' पर विस्तार कर सकते हैं? –

+0

execv को दूसरे पैरा में एक char ** की आवश्यकता है – Alexis

1

आपको सिस्टम के उपयोग से बचना चाहिए।

, साथ सेट उपयोगकर्ता के आईडी या सेट-समूह-आईडी विशेषाधिकार एक कार्यक्रम से प्रणाली() का उपयोग क्योंकि कुछ वातावरण चर के लिए अजीब मूल्य प्रणाली अखंडता को नष्ट करने का इस्तेमाल किया जा सकता है। इसके बजाय फ़ंक्शंस के exec (3) परिवार का उपयोग करें।

और भी आप वापसी मान या कुछ और जांच करने के लिए

बस के लिए execl

#include <unistd.h> 
#include <stdlib.h> 
pid_t pid = fork() 
if (pid == -1) 
{ 
    exit(EXIT_FAILURE); 
} 
else if (pid == 0) 
{ 
    if (execl("processname", "processname", "/path/to/processConfig.xml", NULL) == -1) 
    exit(EXIT_FAILURE); 
} 
else 
... 
0

आप daemon(3) पुस्तकालय समारोह द्वारा रुचि हो सकती है जाना चाहते हैं, तो (आंतरिक दो नेस्टेड fork(2) syscalls का उपयोग कर)। इसके बाद, प्रासंगिक execve(2) syscall (या संबंधित exec(3) फ़ंक्शंस) का उपयोग करें ...

आपको Advanced Linux Programming और अधिक पढ़ने के लिए पढ़ना चाहिए।

4

यह एक छोटा सा पुराना है लेकिन पूरा जवाब नहीं मिला। माता-पिता से कोई संबंध नहीं होने के बावजूद मैंने एक एम्बेडेड सिस्टम पर जो किया है, वह है। ध्यान दें कि मैं एक बैश खोल execl और फिर मेरे आदेश को एक और बैश खोल में चलाएं। यह आपकी स्थिति में आवश्यक नहीं हो सकता है। मेरे लिए यह मुझे कुछ I/O पुनर्निर्देशन करने की अनुमति देता है जो इसके बिना ठीक से काम नहीं करता है।

दो महत्वपूर्ण अवधारणाएं सेटिड() और डबल कांटा() हैं। इन दोनों का संयोजन एक ज़ोंबी को बनाए जाने से रोकता है जब अनाथ बच्चा पूरा होता है, साथ ही माता-पिता को पूरा होने पर अनाथ बच्चे को मारने से रोकता है।

विरासत में आई/ओ हैंडल, कामकाजी निर्देशिका आदि जैसे कई अन्य मुद्दे आ सकते हैं, लेकिन यह कोड मूल नौकरी करता है।

int spawn_orphan(char* cmd) { 
    char command[1024]; // We could segfault if cmd is longer than 1000 bytes or so 
    int pid; 
    int Stat; 
    pid = fork(); 
    if (pid < 0) { perror("FORK FAILED\n"); return pid; } 
    if (pid == 0) { // CHILD 
     setsid(); // Make this process the session leader of a new session 
     pid = fork(); 
     if (pid < 0) { printf("FORK FAILED\n"); exit(1); } 
     if (pid == 0) { // GRANDCHILD 
      sprintf(command,"bash -c '%s'",cmd); 
      execl("/bin/bash", "bash", "-c", command, NULL); // Only returns on error 
      perror("execl failed"); 
      exit(1); 
     } 
     exit(0); // SUCCESS (This child is reaped below with waitpid()) 
    } 

    // Reap the child, leaving the grandchild to be inherited by init 
    waitpid(pid, &Stat, 0); 
    if (WIFEXITED(Stat) && (WEXITSTATUS(Stat) == 0)) { 
     return 0; // Child forked and exited successfully 
    } 
    else { 
     perror("failed to spawn orphan\n"); 
     return -1; 
    } 
} 
0

https://github.com/w-A-L-L-e/wash/blob/master/src/wash.cpp में एक execvp उदाहरण है। पासिंग कमांड लाइन तर्क कभी-कभी निष्पादित करने के साथ एक समस्या है * unistd से कार्य और पर्यावरण पारित होने से कुछ काम हो सकता है। वैसे भी, उम्मीद है कि यह मदद करता है ...

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