পিতামাতার প্রস্থানের পরে কীভাবে শিশু প্রক্রিয়াটি মারা যায়?


209

ধরুন আমার একটি প্রক্রিয়া রয়েছে যা সঠিকভাবে একটি শিশু প্রক্রিয়া তৈরি করে। এখন যখন প্যারেন্ট প্রসেসটি যেকোন কারণে (সাধারণত বা অস্বাভাবিকভাবে মেরে ফেললে, ডিগ্রি সেলসিয়াস, ব্যর্থতা বা অন্য কোনও কিছু দাবি করে) আমি সন্তানের প্রক্রিয়াটি মারা যেতে চাই। কীভাবে এটি সঠিকভাবে করবেন?


স্ট্যাকওভারফ্লো সম্পর্কিত কিছু অনুরূপ প্রশ্ন:


উইন্ডোজের স্ট্যাকওভারফ্লো সম্পর্কিত কিছু অনুরূপ প্রশ্ন :

উত্তর:


189

শিশু বিলি কার্নেল অনুরোধ করতে পারেন SIGHUP(অথবা অন্যান্য সংকেত) যখন বিকল্প নির্দিষ্ট করে পিতা বা মাতা ডাইস PR_SET_PDEATHSIGমধ্যে prctl()ভালো প্রাপ্ত syscall:

prctl(PR_SET_PDEATHSIG, SIGHUP);

দেখুন man 2 prctlবিস্তারিত জানার জন্য।

সম্পাদনা: এটি কেবল লিনাক্স is


5
এটি একটি দুর্বল সমাধান কারণ পিতামাতারা ইতিমধ্যে মারা গিয়েছেন। জাতি শর্ত. সঠিক সমাধান: stackoverflow.com/a/17589555/412080
বচন Egorushkin

16
উত্তর দরিদ্র কল করা খুব সুন্দর নয় - এমনকি এটি যদি কোনও রেসের শর্তটি না দেখায়। রেস-কন্ডিশন মুক্ত উপায়ে কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আমার উত্তর দেখুন prctl()। বিটিডব্লিউ, ম্যাক্সিমের সাথে যুক্ত উত্তরটি ভুল।
ম্যাক্সচলেপজিগ

4
এটি কেবল একটি ভুল প্রতিরোধক। এটি যখন থ্রেডটিকে কাঁটাচামচ বলে ডাকে তখন পিতামাতার প্রক্রিয়াটি মারা যায় না এমন সময় শিশু প্রক্রিয়ায় সংকেত প্রেরণ করবে।
লোথার

2
@ লোথার এক ধরণের প্রমাণ দেখে ভাল লাগবে। man prctlবলেছেন: কলিং প্রক্রিয়াটির প্যারেন্ট প্রসেস ডেথ সিগন্যালটিকে আরগ 2 এ সেট করুন (হয় হয় 1..maxsig, বা 0 সাফের জন্য পরিসরের একটি সংকেত মান)। এটি তার পিতামাতার মৃত্যুর পরে কলিং প্রক্রিয়াটি প্রাপ্তির সংকেত। কোনও সেট-ব্যবহারকারী-আইডি বা সেট-গ্রুপ-আইডি বাইনারি কার্যকর করার সময় এই মানটি কাঁটাচামচ (2) এবং (লিনাক্স 2.4.36 / 2.6.23 সাল থেকে) মুছে ফেলা হয়।
qrdl

1
@ ম্যাক্সচলেপজিগ নতুন লিঙ্কের জন্য ধন্যবাদ। আগের লিঙ্কটি অবৈধ বলে মনে হচ্ছে। যাইহোক, বছর পরে, পিতৃ পক্ষের বিকল্পগুলি সেট করার জন্য এখনও কোনও এপিআই নেই। কি করুণা।
রেক্স

68

আমি একই সমস্যাটি সমাধান করার চেষ্টা করছি এবং যেহেতু আমার প্রোগ্রামটি অবশ্যই ওএস এক্সে চলবে, তাই লিনাক্সের একমাত্র সমাধানটি আমার পক্ষে কার্যকর হয়নি।

আমি এই পৃষ্ঠার অন্যান্য লোকদের মতো একই সিদ্ধান্তে পৌঁছেছি - পিতা-মাতার মৃত্যুর পরে কোনও সন্তানের অবহিত করার কোনও পসিক্স-সামঞ্জস্যপূর্ণ উপায় নেই। তাই আমি পরবর্তী সেরা জিনিসটিকে সরিয়ে দিয়েছি - শিশু জরিপটি করানো।

যখন কোনও পিতামাতার প্রক্রিয়াটি মারা যায় (কোনও কারণে) সন্তানের পিতামাতার প্রক্রিয়াটি প্রক্রিয়াতে পরিণত হয় 1. যদি শিশুটি নিয়মিতভাবে পর্যায়ক্রমে ভোটদান করে তবে এটি তার পিতামাতার ১ কিনা তা পরীক্ষা করতে পারে it যদি এটি হয় তবে শিশুটি প্রস্থান করা উচিত।

এটি দুর্দান্ত নয়, তবে এটি কার্যকর হয়, এবং এই পৃষ্ঠার অন্য কোথাও প্রস্তাবিত টিসিপি সকেট / লকফিল পোলিং সমাধানের চেয়ে সহজ।


6
দুর্দান্ত সমাধান। 1 এবং তারপরে প্রস্থান না হওয়া অবধি অবিরত গেটপিড () কে অনুরোধ করা হচ্ছে। এটি ভাল এবং আমি এখন এটিও ব্যবহার করি। একটি পলিটবিহীন সমাধান যদিও ভাল হবে। ধন্যবাদ শোফ
নিউনি

10
সোলারিসে কেবল তথ্যের জন্য, আপনি যদি কোন জোনে gettpid()থাকেন তবে এটি 1 হয় না তবে pidজোন শিডিয়ুলারের (প্রক্রিয়া zsched) পায়।
প্যাট্রিক Schlüter

4
যদি কেউ ভাবছেন, অ্যান্ড্রয়েড সিস্টেমে পিড মনে হয় 1 এর পরিবর্তে 0 (প্রক্রিয়া সিস্টেম পিড) হয়, যখন পিতামাতার মৃত্যু হয়।
রুই মার্কস

2
এটি করার আরও দৃ rob় এবং প্ল্যাটফর্মের স্বাধীন উপায় থাকার জন্য, কাঁটাচামচ () - এর আগে, কেবল গেটপিড () এবং যদি শিশু থেকে গেটপিড () আলাদা হয় তবে প্রস্থান করুন।
সেবাস্তিয়ান

2
আপনি যদি শিশু প্রক্রিয়াটি নিয়ন্ত্রণ না করেন তবে এটি কাজ করে না। উদাহরণস্বরূপ, আমি একটি কমান্ডে কাজ করছি যা সন্ধানটি (1) মোড়কে দেয় এবং আমি নিশ্চিত করতে চাই যে মোড়কটি কোনও কারণে মারা গেলে অনুসন্ধানটি খুন হয়েছে।
লুক্রেটিয়েল

34

অতীতে আমি "সন্তানের" মধ্যে "আসল" কোড এবং "পিতামাতার" মধ্যে "স্পাঙ্কড" কোড চালিয়ে এটি অর্জন করেছি (এটি: আপনি পরীক্ষার স্বাভাবিক ধারণাটি বিপরীতে পরিণত করেন fork())। তারপরে "তৈরি" কোডটিতে SIGCHLD ফাঁদে ফেলুন ...

আপনার ক্ষেত্রে এটি সম্ভব নাও হতে পারে তবে এটি কার্যকর হলে খুব সুন্দর।


খুব সুন্দর সমাধান, ধন্যবাদ! বর্তমানে গৃহীত এক আরও জেনেরিক তবে আপনার পোর্টেবল আরও।
পাওয়ে হাজদান

1
পিতামাতার কাজটি করার ক্ষেত্রে বিশাল সমস্যাটি হ'ল আপনি পিতামাতার প্রক্রিয়াটি পরিবর্তন করছেন। "চিরকাল" চালাতে হবে এমন কোনও সার্ভারের ক্ষেত্রে, এটি কোনও বিকল্প নয়।
অ্যালেক্সিস উইল্কে

29

আপনি যদি শিশু প্রক্রিয়াটি সংশোধন করতে অক্ষম হন তবে আপনি নীচের মতো কিছু চেষ্টা করতে পারেন:

int pipes[2];
pipe(pipes)
if (fork() == 0) {
    close(pipes[1]); /* Close the writer end in the child*/
    dup2(0, pipes[0]); /* Use reader end as stdin */
    exec("sh -c 'set -o monitor; child_process & read dummy; kill %1'")
}

close(pipes[0]); /* Close the reader end in the parent */

এটি শেল প্রক্রিয়াটির মধ্যে থেকে জব নিয়ন্ত্রণ সক্ষম করার সাথে শিশুটিকে চালিত করে। শিশু প্রক্রিয়াটি পটভূমিতে তৈরি হয়। শেলটি একটি নতুন লাইনের (বা একটি ইওএফ) অপেক্ষা করে তারপরে শিশুটিকে মেরে ফেলে।

যখন পিতামাতা মারা যান - কারণ যাই হোক না কেন - এটি পাইপের শেষটি বন্ধ করে দেবে। চাইল্ড শেলটি পঠন থেকে একটি ইওফ পাবে এবং পটভূমি শিশু প্রক্রিয়াটি মেরে ফেলার জন্য এগিয়ে যাবে।


2
দুর্দান্ত, তবে পাঁচটি সিস্টেম কল, এবং দশ লাইন কোডে ছড়িয়ে দেওয়া এই কোড পারফরম্যান্সের এই অংশটি সম্পর্কে আমাকে কিছুটা সংশয়যুক্ত করতে দেয়।
ওলিয়েড

+1 টি। নির্দিষ্ট ফাইল বর্ণনাকারীর কাছ থেকে পড়ার dup2জন্য read -uপতাকা ব্যবহার করে আপনি স্ট্যান্ড ওভার এড়াতে পারবেন । setpgid(0, 0)টার্মিনালে ^ C টিপে টিপতে বের হওয়া থেকে রোধ করার জন্য আমি বাচ্চাকে একটি যুক্ত করেছিলাম ।
গ্রেগ হিউগিল

dup2()কলটির যুক্তি ক্রমটি ভুল is আপনি pipes[0]স্টিডিন হিসাবে ব্যবহার করতে চাইলে আপনাকে লিখতে dup2(pipes[0], 0)হবে পরিবর্তে dup2(0, pipes[0])। এটা dup2(oldfd, newfd)যেখানে কল পূর্বে খোলা newfd বন্ধ করে।
ম্যাক্সচলেপজিগ

@ ওলিয়েড, আমি সম্মত হই, বিশেষত যেহেতু
স্প্যানড শাই

16

লিনাক্সের অধীনে, আপনি সন্তানের মধ্যে পিতামাতার মৃত্যু সংকেত ইনস্টল করতে পারেন, যেমন:

#include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
#include <signal.h> // signals
#include <unistd.h> // fork()
#include <stdio.h>  // perror()

// ...

pid_t ppid_before_fork = getpid();
pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() != ppid_before_fork)
        exit(1);
    // continue child execution ...

নোট করুন যে কাঁটাচামানের আগে প্যারেন্ট প্রসেস আইডি সংরক্ষণ করে এবং সন্তানের মধ্যে এটি টেস্টিংয়ের পরে prctl()একটি রেস শর্তকে prctl()এবং সেই প্রক্রিয়াটি যেটিকে শিশু বলা হয় তার মধ্য থেকে বেরিয়ে আসে।

এছাড়াও নোট করুন যে সন্তানের পিতামাতার মৃত্যু সংকেতটি তার নিজের তৈরি নতুন শিশুদের মধ্যে সাফ করা হয়েছে। এটি কোনও দ্বারা প্রভাবিত হয় না execve()

এই পরীক্ষাটি সহজ করা যায় যদি আমরা নিশ্চিত যে সমস্ত অনাথকে দত্তক নেওয়ার দায়িত্বে থাকা সিস্টেম প্রক্রিয়াটির পিআইডি 1 রয়েছে:

pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() == 1)
        exit(1);
    // continue child execution ...

initযদিও পিআইডি 1 থাকা সিস্টেম প্রসেসের উপর নির্ভর করা পোর্টেবল নয়। POSIX.1-2008 নির্দিষ্ট করে :

কলিং প্রসেসের বিদ্যমান সমস্ত শিশু প্রক্রিয়া এবং জম্বি প্রক্রিয়াগুলির সকলের প্যারেন্ট প্রসেস আইডি একটি প্রয়োগ-সংজ্ঞায়িত সিস্টেম প্রক্রিয়ার প্রসেস আইডিতে সেট করা হবে। অর্থাৎ, এই প্রক্রিয়াগুলি একটি বিশেষ সিস্টেম প্রক্রিয়া দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত হবে।

Ditionতিহ্যগতভাবে, সমস্ত অনাথকে গ্রহণ করার পদ্ধতি প্রক্রিয়াটি হ'ল পিআইডি 1, অর্থাত্ - যা সমস্ত প্রক্রিয়ার পূর্বপুরুষ।

লিনাক্স বা ফ্রিবিএসডি এর মতো আধুনিক সিস্টেমে অন্য কোনও প্রক্রিয়াতে সেই ভূমিকা থাকতে পারে। উদাহরণস্বরূপ, লিনাক্সে, একটি প্রক্রিয়া prctl(PR_SET_CHILD_SUBREAPER, 1)নিজেকে সিস্টেম প্রক্রিয়া হিসাবে প্রতিষ্ঠিত করতে কল করতে পারে যা তার যে কোনও বংশধরের সমস্ত এতিমকে উত্তরাধিকারী করে তোলে (সিএফ । ফেডোরা 25-তে একটি উদাহরণ )।


আমি বুঝতে পারি না "এই পরীক্ষাটি সরল করা যেতে পারে যদি আমরা নিশ্চিত হয়ে থাকি যে দাদা-মাতামহীরা সর্বদা আরম্ভ প্রক্রিয়া হয়"। যখন কোনও পিতামাতার প্রক্রিয়াটি মারা যায়, তখন কোনও প্রক্রিয়া টিআর প্রক্রিয়া (পিড 1) এর শিশু হয়ে ওঠে, না বাবা-দাদার সন্তান, তাই না? সুতরাং পরীক্ষা সবসময় সঠিক বলে মনে হয়।
জোহানেস স্কাউব -


আকর্ষণীয়, ধন্যবাদ যদিও, দাদা-দাদার সাথে এর কী সম্পর্ক রয়েছে তা আমি দেখতে ব্যর্থ হয়েছি।
জোহানেস স্কাউব -

1
@ জোহানেস শ্যাব-লিটব, আপনি সর্বদা অনুমান করতে পারবেন না যে কোনও প্রক্রিয়াটির দানশীল প্রক্রিয়া হবে init(8).... আপনি কেবল অনুমান করতে পারেন যে যখন কোনও পিতামাতার প্রক্রিয়াটি মারা যায় তখন তার পিতামাতার আইডি পরিবর্তন হবে। এটি আসলে প্রক্রিয়াটির জীবনে একবার ঘটে .... এবং যখন প্রক্রিয়াটির পিতা-মাতার মৃত্যু হয়। শুধুমাত্র এক এই প্রধান ব্যতিক্রম, এবং জন্য init(8)শিশু, কিন্তু আপনার এই থেকে রক্ষা করা হয়, যেমন init(8)কখনো exit(2)(সে ক্ষেত্রে কার্নেল প্যানিক সৃষ্টি)
লুইস কলোরাডো

1
দুর্ভাগ্যক্রমে, যদি কোনও শিশু কোনও থ্রেড থেকে কাঁটাচামচ করে, এবং তারপরে থ্রেডটি প্রস্থান করে, শিশু প্রক্রিয়াটি স্বাক্ষর করবে।
রক্স

14

সম্পূর্ণতার জন্য। ম্যাকোজে আপনি কাকিউ ব্যবহার করতে পারেন:

void noteProcDeath(
    CFFileDescriptorRef fdref, 
    CFOptionFlags callBackTypes, 
    void* info) 
{
    // LOG_DEBUG(@"noteProcDeath... ");

    struct kevent kev;
    int fd = CFFileDescriptorGetNativeDescriptor(fdref);
    kevent(fd, NULL, 0, &kev, 1, NULL);
    // take action on death of process here
    unsigned int dead_pid = (unsigned int)kev.ident;

    CFFileDescriptorInvalidate(fdref);
    CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example

    int our_pid = getpid();
    // when our parent dies we die as well.. 
    LOG_INFO(@"exit! parent process (pid %u) died. no need for us (pid %i) to stick around", dead_pid, our_pid);
    exit(EXIT_SUCCESS);
}


void suicide_if_we_become_a_zombie(int parent_pid) {
    // int parent_pid = getppid();
    // int our_pid = getpid();
    // LOG_ERROR(@"suicide_if_we_become_a_zombie(). parent process (pid %u) that we monitor. our pid %i", parent_pid, our_pid);

    int fd = kqueue();
    struct kevent kev;
    EV_SET(&kev, parent_pid, EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
    kevent(fd, &kev, 1, NULL, 0, NULL);
    CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, true, noteProcDeath, NULL);
    CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
    CFRunLoopSourceRef source = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
    CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}

আপনি DISPATCH_SOURCE_PROC এবং PROC_EXIT এর সাথে প্রেরণ উত্স ব্যবহার করে কিছুটা নিখর এপিআই দিয়ে এটি করতে পারেন।
রাশিবিশপ

যে কারণেই হোক না কেন, এটি আমার ম্যাককে আতঙ্কিত করছে। এই কোডটি দিয়ে একটি প্রক্রিয়া চালানোর একটি 50% বা তার বেশি জমির সম্ভাবনা রয়েছে, ভক্তরা এমন হারে ঘুরপাক খায় যা আমি তাদের (সুপার দ্রুত) এর আগে কখনও শুনিনি, এবং ম্যাকটি বন্ধ হয়ে যায়। এই কোড সহ খুব যত্নশীল হন
কিউস - মনোকা

আমার ম্যাকোস-এ দেখে মনে হচ্ছে, পিতামাতার প্রস্থানের পরে শিশু প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে প্রস্থান করে। কেন জানি না।
ইয়ি লিন লিউ

@YiLinLiu iirc আমি ব্যবহৃত NSTaskবা পিক্সিক্স স্প্যান করি। startTaskএখানে আমার কোডটিতে
নিউনি

11

সন্তানের প্রক্রিয়াটি কি পিতামাতার প্রক্রিয়াটিতে / থেকে পাইপ পায়? যদি তা হয় তবে আপনি লেখার জন্য একটি সাইনপাইপ পেয়েছেন, বা পড়ার সময় ইওএফ পাবেন - এই শর্তগুলি সনাক্ত করা যায়।


1
আমি দেখেছি এটি নির্ভরযোগ্যভাবে ঘটেনি, কমপক্ষে ওএস এক্স-এ
শোফ

আমি এই উত্তর যুক্ত করতে এখানে এসেছি। আমি অবশ্যই এই ক্ষেত্রে এটি সমাধান করব।
দোলডা 2000

সাবধানতার বিষয়টি: সিস্টেমড পরিচালিত পরিষেবাদিগুলিতে ডিফল্টরূপে সিগপিপগুলি অক্ষম করে, তবে আপনি এখনও পাইপ বন্ধের জন্য পরীক্ষা করতে পারেন। IgnoreSIGPIPE
jdizzle

11

এখানে অন্য উত্তরে অনুপ্রাণিত হয়ে আমি নিম্নলিখিত সমস্ত-পসিক্স সমাধানটি নিয়ে এসেছি। সাধারণ ধারণাটি হল পিতামাতার এবং সন্তানের মধ্যে একটি মধ্যবর্তী প্রক্রিয়া তৈরি করা, যার একটি উদ্দেশ্য রয়েছে: পিতামাতা মারা যাওয়ার সময় লক্ষ্য করুন এবং স্পষ্টভাবে শিশুটিকে হত্যা করবেন।

এই ধরণের সমাধান কার্যকর হয় যখন সন্তানের কোডটি সংশোধন করা যায় না।

int p[2];
pipe(p);
pid_t child = fork();
if (child == 0) {
    close(p[1]); // close write end of pipe
    setpgid(0, 0); // prevent ^C in parent from stopping this process
    child = fork();
    if (child == 0) {
        close(p[0]); // close read end of pipe (don't need it here)
        exec(...child process here...);
        exit(1);
    }
    read(p[0], 1); // returns when parent exits for any reason
    kill(child, 9);
    exit(1);
}

এই পদ্ধতি সহ দুটি ছোট ক্যাভেট রয়েছে:

  • আপনি যদি ইচ্ছাকৃতভাবে মধ্যবর্তী প্রক্রিয়াটি হত্যা করেন তবে পিতামাতার মৃত্যুর পরে বাচ্চাকে হত্যা করা হবে না।
  • যদি শিশুটি পিতামাতার আগে উপস্থিত হয়, তবে মধ্যবর্তী প্রক্রিয়াটি মূল চাইল্ড পিডকে মেরে ফেলার চেষ্টা করবে, যা এখন অন্যরকম প্রক্রিয়া উল্লেখ করতে পারে। (এটি মধ্যবর্তী প্রক্রিয়াতে আরও কোড সহ স্থির করা যেতে পারে))

সরাইয়া হিসাবে, আমি যে প্রকৃত কোডটি ব্যবহার করছি তা পাইথনে। এখানে এটি সম্পূর্ণতার জন্য:

def run(*args):
    (r, w) = os.pipe()
    child = os.fork()
    if child == 0:
        os.close(w)
        os.setpgid(0, 0)
        child = os.fork()
        if child == 0:
            os.close(r)
            os.execl(args[0], *args)
            os._exit(1)
        os.read(r, 1)
        os.kill(child, 9)
        os._exit(1)
    os.close(r)

মনে রাখবেন কিছুক্ষণ আগে, আইআরআইএক্স এর অধীনে, আমি একটি পিতামাতার / শিশু স্কিমটি ব্যবহার করেছি যেখানে আমার উভয়ের মধ্যে পাইপ ছিল এবং পাইপ থেকে পড়ার ফলে একজনের মৃত্যু হয় তবে সাইনআপ তৈরি করে। মধ্যবর্তী প্রক্রিয়াটির প্রয়োজন ছাড়াই আমি আমার কাঁটাচামচ () 'এড বাচ্চাদের মেরে ফেলতাম।
অ্যালেক্সিস উইল্ক

আমি মনে করি আপনার দ্বিতীয় সতর্কতা ভুল is সন্তানের পিড হ'ল এটি তার পিতা-মাতার মালিকানাধীন একটি সম্পদ এবং যতক্ষণ না পিতামাতা (মধ্যবর্তী প্রক্রিয়া) এটির জন্য অপেক্ষা করে না (বা শেষ করে দেয় এবং এটির জন্য অপেক্ষা করতে দেয়) ততক্ষণ এটি মুক্ত / পুনরায় ব্যবহার করা যাবে না।
আর .. গিথহাব বন্ধ করুন ICE

7

আমি বিশ্বাস করি না যে কেবলমাত্র স্ট্যান্ডার্ড পসিক্স কল ব্যবহার করে গ্যারান্টি দেওয়া সম্ভব। বাস্তব জীবনের মতো, একবার বাচ্চা জন্মালে তার নিজস্ব জীবন হয়।

এটা হয় পিতা বা মাতা প্রক্রিয়া অধিকাংশ সম্ভব পরিসমাপ্তি ঘটনা ধরা, এবং যে সময়ে সন্তান প্রক্রিয়া হত্যা করার প্রচেষ্টা করা সম্ভব, কিন্তু সবসময় কিছু যে ধরা যাবে না করে।

উদাহরণস্বরূপ, কোনও প্রক্রিয়া একটি ধরতে পারে না SIGKILL । যখন কার্নেল এই সংকেতটি পরিচালনা করে তখন নির্দিষ্ট প্রক্রিয়াটিকে কোনও প্রকারের প্রজ্ঞাপন ছাড়াই হত্যা করে।

সাদৃশ্যটি প্রসারিত করা - এটি করার একমাত্র অন্যান্য স্ট্যান্ডার্ড উপায় হ'ল সন্তানের আত্মহত্যা করা যখন এটি জানতে পারে যে তার বাবা-মা নেই।

এটি দিয়ে লিনাক্সের একমাত্র উপায় রয়েছে prctl(2)- অন্যান্য উত্তর দেখুন।


6

অন্যান্য লোকেরা যেমন উল্লেখ করেছে, পিতামাতার বাইরে বেরোনোর ​​সময় পোর্টেন্টের বাইরে বেরোনোর ​​সময় 1 হয়ে যাওয়ার জন্য প্যারেন্ট পিডের উপর নির্ভর করে। নির্দিষ্ট অভিভাবক প্রসেস আইডির জন্য অপেক্ষা না করে কেবল আইডিটি পরিবর্তনের জন্য অপেক্ষা করুন:

pit_t pid = getpid();
switch (fork())
{
    case -1:
    {
        abort(); /* or whatever... */
    }
    default:
    {
        /* parent */
        exit(0);
    }
    case 0:
    {
        /* child */
        /* ... */
    }
}

/* Wait for parent to exit */
while (getppid() != pid)
    ;

আপনি সম্পূর্ণ গতিতে পোল করতে না চাইলে পছন্দসই হিসাবে একটি মাইক্রো-স্লিপ যুক্ত করুন।

পাইপ ব্যবহার করা বা সিগন্যালের উপর নির্ভর করার চেয়ে এই বিকল্পটি আমার কাছে সহজ বলে মনে হচ্ছে।


দুর্ভাগ্যক্রমে, সমাধানটি শক্তিশালী নয়। প্রাথমিক মূল্য পাওয়ার আগে পিতামাতার প্রক্রিয়াটি মারা গেলে কী হবে? শিশুটি কখনই বাইরে বেরোবে না।
ডিগাটউড

@ ডিগাটউড, আপনার মানে কী?!? getpid()কল করার আগে প্রথম পিতামাতার মধ্যে সম্পন্ন হয় fork()। এর আগে বাবা-মা মারা গেলে সন্তানের অস্তিত্ব থাকে না। যা হতে পারে তা হল শিশুটি কিছু সময়ের জন্য পিতামাতার বাইরে থাকতে পারে।
অ্যালেক্সিস উইল্কে

এই কিছুটা স্বীকৃত উদাহরণে এটি কাজ করে, তবে বাস্তব-বিশ্ব কোডে কাঁটাচামচ প্রায় সবসময়ই এক্সিকিউট দ্বারা অনুসরণ করা হয় এবং নতুন পিপিআইডি জিজ্ঞাসা করে নতুন প্রক্রিয়াটি শুরু করতে হবে। এই দুটি চেকের মধ্যে সময়ের মধ্যে, যদি বাবা-মা চলে যায় তবে সন্তানের কোনও ধারণা থাকবে না। এছাড়াও, পিতা বা মাতা এবং সন্তানের উভয় কোডের উপর আপনার নিয়ন্ত্রণের সম্ভাবনা নেই (অন্যথায় আপনি কেবল যুক্তি হিসাবে পিপিআইডি পাস করতে পারেন)। সুতরাং একটি সাধারণ সমাধান হিসাবে, এই পদ্ধতির খুব ভাল কাজ করে না। এবং বাস্তববাদী, যদি কোনও ইউনিক্স-এর মতো ওএস 1 টি না করে বাইরে চলে আসে, এত বেশি জিনিস ভেঙে যায় যে আমি যে কোনওভাবেই এটি করার কল্পনা করতে পারি না।
ডিগাটউড

সন্তানের জন্য এক্সিকিউট করার সময় পাস প্যারেন্ট পিড হ'ল কমান্ড লাইন আর্গুমেন্ট।
নিশ

2
পূর্ণ গতিতে পোলিং পাগল।
ম্যাক্সচলেপজিগ

4

সিগিন্ট ধরার জন্য একটি ট্র্যাপ হ্যান্ডলার ইনস্টল করুন , এটি এখনও জীবিত থাকলে আপনার সন্তানের প্রক্রিয়াটি বন্ধ করে দেয়, যদিও অন্যান্য পোস্টারগুলি ঠিক আছে যে এটি সিগ্কিলকে ধরবে না।

একচেটিয়া অ্যাক্সেস সহ একটি লকফায়াল খুলুন এবং এটিতে শিশু পোলটি এটি খোলার চেষ্টা করুন - খোলা সফল হলে, শিশু প্রক্রিয়াটি প্রস্থান করা উচিত


বা, বাচ্চাটি ব্লকিং মোডে একটি পৃথক থ্রেডে লকফিলটি খুলতে পারে, এক্ষেত্রে এটি একটি সুন্দর এবং পরিষ্কার সমাধান হতে পারে। সম্ভবত এটির কিছু পোর্টেবিলিটি সীমাবদ্ধতা রয়েছে যদিও।
জিন 14

4

এই সমাধানটি আমার পক্ষে কাজ করেছে:

  • সন্তানের কাছে স্টিডিন পাইপ পাস করুন - আপনার প্রবাহে কোনও ডেটা লিখতে হবে না।
  • শিশু স্ট্যান্ডিন থেকে ইওএফ পর্যন্ত অনির্দিষ্টকালের জন্য পড়ে। একটি ইওএফ সংকেত দেয় যে পিতামাতারা চলে গেছেন।
  • পিতামাতারা কখন চলে গেছে তা সনাক্ত করার জন্য এটি নির্বোধ এবং পোর্টেবল উপায়। এমনকি পিতামাতার ক্রাশ হয়ে গেলেও ওএস পাইপটি বন্ধ করে দেবে।

এটি এমন শ্রমিক-প্রক্রিয়াকরণের জন্য ছিল যার অস্তিত্ব কেবল তখনই উপলব্ধি হয়েছিল যখন পিতা-মাতা বেঁচে ছিলেন।


@ সেবাস্তিয়ান জিলানকি আমি চেষ্টা করেছি কিনা মনে নেই তবে এটি সম্ভবত কাজ করে কারণ আদিম (পসিক্স স্ট্রিম) ওএসের জুড়ে মোটামুটি মানক।
junas.fi

3

আমি মনে করি একটি দ্রুত এবং নোংরা উপায় হ'ল সন্তান এবং পিতামাতার মধ্যে পাইপ তৈরি করা। যখন পিতামাতারা প্রস্থান করেন, বাচ্চারা একটি স্বাক্ষর গ্রহণ করবে।


পাইপ বন্ধে সাইনপাইপ প্রেরণ করা হয় না, কেবল তখনই পাঠানো হয় যখন শিশুটি এটি লেখার চেষ্টা করে।
অ্যালাকারো 11

3

কিছু পোস্টার ইতিমধ্যে পাইপ এবং উল্লেখ করেছে kqueue। প্রকৃতপক্ষে আপনি কল করে সংযুক্ত ইউনিক্স ডোমেন সকেটেরও একটি জুড়ি তৈরি করতে পারেন socketpair()। সকেটের ধরণটি হওয়া উচিত SOCK_STREAM

আমাদের ধরুন আপনার কাছে দুটি সকেট ফাইল বর্ণনাকারী fd1, fd2 রয়েছে। এখন fork()শিশু প্রক্রিয়া তৈরি করতে, যা এইচডিএসের উত্তরাধিকারী হবে। পিতামাতার মধ্যে আপনি fd2 এবং সন্তানের মধ্যে আপনি fd1 বন্ধ করেন। এখন প্রতিটি প্রক্রিয়া ইভেন্টের poll()জন্য নিজস্ব প্রান্তে বাকি ওপেন এফডি করতে পারে POLLIN। যতক্ষণ না প্রতিটি পক্ষই close()স্বাভাবিক জীবনকাল চলাকালীন স্পষ্টভাবে তার এফডি না করে , আপনি মোটামুটি নিশ্চিত হতে পারেন যে কোনও POLLHUPপতাকা অন্যটির সমাপ্তি নির্দেশ করবে (পরিষ্কার পরিষ্কার হোক না কেন)। এই ইভেন্টটি অবহিত হওয়ার পরে, শিশু কী করবে (যেমন মরতে হবে) সিদ্ধান্ত নিতে পারে।

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
    int sv[2];        /* sv[0] for parent, sv[1] for child */
    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);

    pid_t pid = fork();

    if ( pid > 0 ) {  /* parent */
        close(sv[1]);
        fprintf(stderr, "parent: pid = %d\n", getpid());
        sleep(100);
        exit(0);

    } else {          /* child */
        close(sv[0]);
        fprintf(stderr, "child: pid = %d\n", getpid());

        struct pollfd mon;
        mon.fd = sv[1];
        mon.events = POLLIN;

        poll(&mon, 1, -1);
        if ( mon.revents & POLLHUP )
            fprintf(stderr, "child: parent hung up\n");
        exit(0);
    }
}

আপনি উপরের প্রুফ-অফ-কনসেপ্ট কোডটি সংকলনের চেষ্টা করতে পারেন, এবং এটিকে টার্মিনালে চালাতে পারেন ./a.out &। বিভিন্ন সিগন্যাল দ্বারা প্যারেন্ট পিআইডি হত্যার জন্য পরীক্ষা করতে আপনার মোটামুটি 100 সেকেন্ড রয়েছে, অথবা এটি কেবল প্রস্থান করবে। উভয় ক্ষেত্রেই আপনার "বাচ্চা: পিতামাতাকে ফাঁসি দেওয়া" বার্তাটি দেখতে হবে।

SIGPIPEহ্যান্ডলার ব্যবহারের পদ্ধতির সাথে তুলনা করে , এই পদ্ধতির জন্য write()কল চেষ্টা করার প্রয়োজন নেই ।

এই পদ্ধতিটিও প্রতিসম , অর্থাৎ প্রক্রিয়াগুলি একে অপরের অস্তিত্ব নিরীক্ষণ করতে একই চ্যানেলটি ব্যবহার করতে পারে।

এই সমাধানটি কেবল পসিক্স ফাংশনগুলিকে কল করে। আমি লিনাক্স এবং ফ্রিবিএসডি-তে এটি চেষ্টা করেছি। আমি মনে করি এটি অন্যান্য ইউনিক্সগুলিতে কাজ করা উচিত তবে আমি সত্যিই পরীক্ষা করি নি।

আরো দেখুন:

  • unix(7)লিনাক্স মানুষ পৃষ্ঠাগুলির, unix(4)FreeBSD 'র জন্য, poll(2), socketpair(2), socket(7)লিনাক্স।

খুব দুর্দান্ত, আমি সত্যিই ভাবছি যদিও এর কোনও নির্ভরযোগ্যতা সমস্যা আছে কিনা। আপনি কি পরীক্ষায় এটি পরীক্ষা করেছেন? বিভিন্ন অ্যাপস দিয়ে?
আকতাউ

@ আকতাউ, আমি একটি লিনাক্স প্রোগ্রামে পাইথনের সমতুল্য এই কৌশলটির ব্যবহার করছি। আমার এটির প্রয়োজন ছিল কারণ সন্তানের কাজের যুক্তি হ'ল "পিতা-মাতার বাইরে বেরোনোর ​​পরে সর্বোত্তম প্রচেষ্টা চালিয়ে যাওয়া এবং তারপরে খুব বেরিয়ে আসা"। তবে আমি অন্যান্য প্ল্যাটফর্মগুলি সম্পর্কে সত্যই নিশ্চিত নই। সি স্নিপেট লিনাক্স এবং ফ্রিবিএসডি-তে কাজ করে তবে এটাই আমি জানি ... এছাড়াও, আপনার ক্ষেত্রে যত্নশীল হওয়া উচিত, যেমন পিতামাতাকে আবার কাঁটাচামচা করা, বা পিতামাতারা সত্যিকার অর্থে বেরিয়ে আসার আগে এফডি ত্যাগ করেন (এভাবে একটি সময় উইন্ডো তৈরি করা যায় জাতি শর্ত).
কংগা মা

@ আকতাউ - এটি সম্পূর্ণ নির্ভরযোগ্য হবে।
সর্বজনীন

1

অধীনে POSIX , exit(), _exit()এবং _Exit()ফাংশন সংজ্ঞায়িত করা হয়:

  • যদি প্রক্রিয়াটি একটি নিয়ন্ত্রণকারী প্রক্রিয়া হয়, কলিং প্রক্রিয়াভুক্ত নিয়ন্ত্রণকারী টার্মিনালের অগ্রভাগ প্রক্রিয়া গোষ্ঠীর প্রতিটি প্রক্রিয়াতে SIGHUP সিগন্যাল প্রেরণ করা হবে।

সুতরাং, যদি আপনি পিতামাতার প্রক্রিয়াটিকে তার প্রক্রিয়া গোষ্ঠীর জন্য একটি নিয়ন্ত্রণকারী প্রক্রিয়া হিসাবে রাখার ব্যবস্থা করেন তবে পিতা-মাতার প্রস্থানটি প্রকাশের পরে সন্তানের একটি সিএইচএইচপি সংকেত পাওয়া উচিত। আমি পুরোপুরি নিশ্চিত নই যে পিতা বা মাতা ক্রাশ হওয়ার পরে ঘটেছিল, তবে আমি মনে করি এটি ঘটে। অবশ্যই, ক্র্যাশবিহীন কেসের ক্ষেত্রে এটি ঠিকঠাক কাজ করা উচিত।

নোট তুমি ভাল মুদ্রণ বেশ অনেক পড়তে থাকতে পারে - জন্য বেজ সংজ্ঞা (সংজ্ঞা) ধারা সহ, সেইসাথে সিস্টেম সার্ভিস তথ্য exit()এবং setsid()এবং setpgrp()- সম্পূর্ণ ছবি পেতে। (তাই আমি চাই!)


3
হুম। ডকুমেন্টেশন এ সম্পর্কে অস্পষ্ট এবং বিপরীত, তবে এটি প্রদর্শিত হয় যে পিতামাতার প্রক্রিয়াটি কেবল প্রক্রিয়া গোষ্ঠী নয়, অধিবেশনটির নেতৃত্ব প্রক্রিয়া হতে হবে। অধিবেশনটির নেতৃত্বের প্রক্রিয়াটি সর্বদা লগইন ছিল এবং নতুন অধিবেশনটির নেতৃত্বের প্রক্রিয়া হিসাবে গ্রহণ করার প্রক্রিয়াটি আমার সামর্থ্যের বাইরে ছিল ab
শোফ

2
সাইনআপ কার্যকরভাবে কেবলমাত্র শিশু প্রক্রিয়াগুলিতে প্রেরণ করা হবে যদি প্রস্থানকারী প্রক্রিয়াটি লগইন শেল হয়। opengroup.org/onlinepubs/009695399/funitions/exit.html "কোনও প্রক্রিয়া সমাপ্তি তার শিশুদের সরাসরি সমাপ্ত করে না below
রব কে

1
@ রব: সঠিক - আমি যে উদ্ধৃতি দিয়েছি তাও বলেছেন: কেবলমাত্র কিছু পরিস্থিতিতে শিশু প্রক্রিয়াটি একটি সিএইচএইচপি দেয়। এবং এটি কঠোরভাবে অতি সরলকরণ যা এটি সর্বাধিক সাধারণ ঘটনা সত্ত্বেও এটি কেবল লগইন শেল যা SIGHUP প্রেরণ করে। যদি একাধিক বাচ্চাদের নিয়ে কোনও প্রক্রিয়া নিজেকে এবং তার বাচ্চাদের জন্য নিয়ন্ত্রণ প্রক্রিয়া হিসাবে নিজেকে সেট করে, তবে মাস্টার মারা গেলে সাইনআপটি (স্বাচ্ছন্দ্যে) তার বাচ্চাদের কাছে প্রেরণ করা হবে। ওও, প্রক্রিয়াগুলি খুব কমই খুব ঝামেলা হয় - তাই আমি একটি সত্যিকারের উল্লেখযোগ্য দ্বিধা বাড়ানোর চেয়ে আরও বেশি বাছাই করি।
জোনাথন লেফলার

2
আমি এটি কয়েক ঘন্টা জন্য এটি প্রায় বোকা এবং এটি কাজ পেতে না পারে। এটি খুব সুন্দরভাবে একটি কেস পরিচালনা করতে পারে যেখানে কিছু বাচ্চাদের সাথে আমার ডেমন থাকে যা পিতামাতার বাইরে চলে যাওয়ার পরে সকলেরই মারা যাওয়ার দরকার হয়।
রব কে

1

উদাহরণস্বরূপ আপনি যদি পিড 0 তে একটি সংকেত প্রেরণ করেন

kill(0, 2); /* SIGINT */

এই সংকেতটি পুরো প্রক্রিয়া গোষ্ঠীতে প্রেরণ করা হয়, যাতে কার্যকরভাবে শিশুটিকে হত্যা করা হয়।

আপনি এ জাতীয় কিছু দিয়ে এটি সহজে পরীক্ষা করতে পারেন:

(cat && kill 0) | python

আপনি যদি ডি press ডি টিপেন, আপনি পাঠ্যটি "Terminated"একটি ইঙ্গিত হিসাবে দেখতে পাবেন যে স্টিডিন বন্ধ থাকার কারণে কেবল পাইথন দোভাষীকে হত্যা করা হয়েছে instead


1
(echo -e "print(2+2)\n" & kill 0) | sh -c "python -" খুশির সাথে
সমাপ্তির

1

যদি এটি অন্য কারও পক্ষে প্রাসঙ্গিক হয়, আমি যখন সিভি ++ থেকে জেভিএম উদাহরণগুলি কাঁটাচানা শিশু প্রসেসগুলিতে উত্সাহিত করি তখন পিতামাতার প্রক্রিয়াটি সমাপ্ত হওয়ার পরে জেভিএম দৃষ্টান্তগুলি সঠিকভাবে শেষ করতে পেতাম কেবলমাত্র নিম্নলিখিত পদ্ধতিগুলি হ'ল। আশা করি কেউ যদি এটি করার সর্বোত্তম উপায় না হন তবে মন্তব্যে প্রতিক্রিয়া জানাতে পারেন।

1) এবং এর prctl(PR_SET_PDEATHSIG, SIGHUP)মাধ্যমে জাভা অ্যাপ্লিকেশন চালু করার আগে প্রস্তাবিত কাঁটাযুক্ত শিশু প্রক্রিয়া কল করুনexecv

2) জাভা অ্যাপ্লিকেশন নির্বাচনে তার পিতা বা মাতা পর্যন্ত PID, সমান 1, তারপর একটি হার্ড করতে শাটডাউন হুক যোগ করুন Runtime.getRuntime().halt(0)psকমান্ডটি চালায় এমন একটি পৃথক শেল চালু করে ভোটগ্রহণটি করা হয় (দেখুন: আমি জাভাতে আমার পিআইডি বা লিনাক্সে জেআরবি কীভাবে খুঁজে পাব? )

সম্পাদনা 130118:

মনে হচ্ছে এটি একটি শক্তিশালী সমাধান ছিল না। যা চলছে তার সংক্ষিপ্তসারগুলি বুঝতে আমি এখনও কিছুটা লড়াই করছি, তবে স্ক্রিন / এসএসএইচ সেশনে এই অ্যাপ্লিকেশনগুলি চালানোর সময় আমি কখনও কখনও অনাথ জেভিএম প্রক্রিয়াগুলি পেয়ে যাচ্ছিলাম।

জাভা অ্যাপ্লিকেশনে পিপিআইডি-র জন্য ভোটদানের পরিবর্তে আমি কেবল বন্ধ হিসাবে হুক ক্লিনআপ সম্পাদন করেছিলাম এবং তারপরে উপরের মতো একটি হার্ড স্টপ করা উচিত। তারপরে আমি নিশ্চিত করেছিলাম যে waitpidসবকিছু শেষ করার সময় হয়ে ওঠার পরে শিশু প্রসেসের C ++ প্যারেন্ট অ্যাপটিতে আবেদন করা উচিত। এটি একটি আরও দৃ solution় সমাধান বলে মনে হচ্ছে, শিশু প্রক্রিয়াটি এটি সমাপ্ত হওয়ার বিষয়টি নিশ্চিত করে, যখন পিতামাতারা তার সন্তানদের সমাপ্ত করে দেয় তা নিশ্চিত করার জন্য বিদ্যমান রেফারেন্সগুলি ব্যবহার করে। এটি পূর্ববর্তী সমাধানের সাথে তুলনা করুন যা অভিভাবক প্রক্রিয়াটি যখনই খুশি হয়, এবং সন্তানের সমাপ্তির আগে এতিম হয়েছে কিনা তা নির্ধারণ করার চেষ্টা করেছিল।


1
PID equals 1অপেক্ষার বৈধ নয়। নতুন পিতা বা মাতা অন্য কোনও পিআইডি হতে পারে। কাঁটাচামচ () এর আগে ডাকা হওয়ার সময় সন্তানের গেটপিড () এর সমান নয় সন্তানের নতুন প্যারেন্ট (গেটপিড () থেকে কাঁটাচামচ () এর পূর্বে এটি মূল পিতা (গেটপিড () থেকে পরিবর্তিত হয় কিনা তা আপনার পরীক্ষা করা উচিত।
অ্যালেক্সিস উইল্কে

1

লিনাক্স নির্দিষ্ট এটি করার আরেকটি উপায় হ'ল পিতামাতাকে একটি নতুন পিআইডি নেমস্পেসে তৈরি করা উচিত। এরপরে সেই নামটির জায়গার পিআইডি 1 হবে এবং এটি যখন এটি থেকে বেরিয়ে আসে তখন তার সমস্ত বাচ্চাকে সঙ্গে সঙ্গে হত্যা করা হবে SIGKILL

দুর্ভাগ্যক্রমে, একটি নতুন পিআইডি নেমস্পেস তৈরি করতে আপনার থাকতে হবে CAP_SYS_ADMIN। তবে, এই পদ্ধতিটি অত্যন্ত কার্যকর এবং পিতামাতার প্রাথমিক প্রবর্তনের বাইরে পিতা বা মাতা বাচ্চাদের কোনও আসল পরিবর্তন প্রয়োজন।

দেখুন ক্লোন (2) , pid_namespaces (7) , এবং ভাগ করা তুলে নিন (2)


আমার অন্যভাবে সম্পাদনা করা দরকার। এটির সমস্ত শিশু এবং নাতি-নাতনি, এবং নাতি-নাতনী ইত্যাদির জন্য প্রসেস অ্যাক্ট হিসাবে প্র্যাক্টেল ব্যবহার করা সম্ভব ...
সর্বজনীন

0

যদি পিতামাতার মৃত্যু হয়, তবে অনাথদের পিপিআইডি 1 তে পরিবর্তিত হয় - আপনাকে কেবল নিজের পিপিআইডি পরীক্ষা করতে হবে। এক উপায়ে, এটি ভোটদান, উপরে বর্ণিত। এখানে তার জন্য শেল পিস রয়েছে:

check_parent () {
      parent=`ps -f|awk '$2=='$PID'{print $3 }'`
      echo "parent:$parent"
      let parent=$parent+0
      if [[ $parent -eq 1 ]]; then
        echo "parent is dead, exiting"
        exit;
      fi
}


PID=$$
cnt=0
while [[ 1 = 1 ]]; do
  check_parent
  ... something
done

0

আমি দুটি সমাধান পেয়েছি, উভয়ই নিখুঁত নয়।

1. সিগন্যারএম সিগন্যাল পেলে সমস্ত শিশুকে হত্যা (-পিড) মারুন।
স্পষ্টতই, এই সমাধানটি "কিল -9" পরিচালনা করতে পারে না, তবে এটি বেশিরভাগ ক্ষেত্রে এবং খুব সহজ কাজ করে কারণ এটি সমস্ত শিশু প্রক্রিয়া মনে রাখার দরকার নেই।


    var childProc = require('child_process').spawn('tail', ['-f', '/dev/null'], {stdio:'ignore'});

    var counter=0;
    setInterval(function(){
      console.log('c  '+(++counter));
    },1000);

    if (process.platform.slice(0,3) != 'win') {
      function killMeAndChildren() {
        /*
        * On Linux/Unix(Include Mac OS X), kill (-pid) will kill process group, usually
        * the process itself and children.
        * On Windows, an JOB object has been applied to current process and children,
        * so all children will be terminated if current process dies by anyway.
        */
        console.log('kill process group');
        process.kill(-process.pid, 'SIGKILL');
      }

      /*
      * When you use "kill pid_of_this_process", this callback will be called
      */
      process.on('SIGTERM', function(err){
        console.log('SIGTERM');
        killMeAndChildren();
      });
    }

একইভাবে, আপনি প্রসেস.এক্সিটিকে কোথাও কল করলে আপনি উপরের মতো 'প্রস্থান' হ্যান্ডলার ইনস্টল করতে পারেন। দ্রষ্টব্য: Ctrl + C এবং আকস্মিক ক্র্যাশ ওএস দ্বারা স্বয়ংক্রিয়ভাবে প্রক্রিয়া করা হয়েছে প্রক্রিয়া গোষ্ঠীটি হত্যা করার জন্য, সুতরাং এখানে আর নেই।

2.Use chjj / pty.js করার ডিম আপনার টার্মিনাল সংযুক্ত নিয়ন্ত্রণ সঙ্গে প্রক্রিয়া।
আপনি বর্তমান প্রক্রিয়াটিকে যেভাবেই মেরে ফেলেন এমনকি এমনকি হত্যা -9 করুন, সমস্ত শিশু প্রক্রিয়াগুলি স্বয়ংক্রিয়ভাবে মারা যাবে (ওএস দ্বারা?) আমি অনুমান করি যেহেতু বর্তমান প্রক্রিয়াটি টার্মিনালের অন্য দিকে ধারণ করে, সুতরাং যদি বর্তমান প্রক্রিয়াটি মারা যায় তবে শিশু প্রক্রিয়াটি এসআইপিআইপিইপিতে মারা যায় তাই মারা যায়।


    var pty = require('pty.js');

    //var term =
    pty.spawn('any_child_process', [/*any arguments*/], {
      name: 'xterm-color',
      cols: 80,
      rows: 30,
      cwd: process.cwd(),
      env: process.env
    });
    /*optionally you can install data handler
    term.on('data', function(data) {
      process.stdout.write(data);
    });
    term.write(.....);
    */

0

আমি টার্মিনাল নিয়ন্ত্রণ এবং সেশনগুলিকে আপত্তিজনকভাবে 3 টি প্রক্রিয়া সহ একটি পোর্টেবল, অ-পোলিং সমাধান করতে পেরেছি। এটি মানসিক হস্তমৈথুন, কিন্তু কাজ করে।

কৌশলটি হ'ল:

  • প্রক্রিয়া এ শুরু হয়
  • প্রক্রিয়া এ একটি পাইপ পি তৈরি করে (এবং এটি কখনও পড়েনা)
  • প্রক্রিয়া A প্রক্রিয়া বি এ কাঁটাচামচ
  • প্রক্রিয়া বি একটি নতুন অধিবেশন তৈরি করে
  • প্রক্রিয়া বি সেই নতুন অধিবেশনটির জন্য ভার্চুয়াল টার্মিনাল বরাদ্দ করে
  • প্রক্রিয়া বি শিশুটি প্রস্থান করার সময় মারা যাওয়ার জন্য সাইনচএলডি হ্যান্ডলার ইনস্টল করে
  • প্রক্রিয়া বি একটি SIGPIPE হ্যান্ডলার সেট করে
  • প্রক্রিয়া বি প্রক্রিয়া সিতে কাঁটাচামচ
  • প্রক্রিয়া সি যা প্রয়োজন তা করে (উদাহরণস্বরূপ এক্সিকিউট () অবিস্মরণিত বাইনারি বা যা যুক্তি চালায়)
  • প্রক্রিয়া বি পাইপ পিতে লিখেছেন (এবং সেভাবে অবরুদ্ধ করে)
  • প্রক্রিয়া বি প্রক্রিয়া বিতে একটি অপেক্ষা (গুলি) হয় এবং এটি মারা যাওয়ার পরে প্রস্থান করে

ঐ দিকে:

  • যদি প্রক্রিয়া এ মারা যায়: প্রক্রিয়া বি একটি স্বাক্ষর পায় এবং মারা যায়
  • যদি প্রক্রিয়া বি মারা যায়: প্রক্রিয়া এ এর ​​অপেক্ষা () প্রত্যাবর্তন করে এবং মারা যায়, প্রক্রিয়া সি একটি সাইনগআপ পায় (কারণ যখন টার্মিনাল সংযুক্ত একটি সেশনের অধিবেশন নেতা মারা যায়, অগ্রভাগ প্রক্রিয়া গোষ্ঠীর সমস্ত প্রক্রিয়া একটি সাইনআপ হয়)
  • যদি প্রক্রিয়া সি মারা যায়: প্রক্রিয়া বি একটি সিএইচসিএলডি পায় এবং মারা যায়, তাই প্রক্রিয়া এ মারা যায়

ভুলত্রুটি:

  • প্রক্রিয়া সি SIGHUP পরিচালনা করতে পারে না
  • প্রক্রিয়া সি একটি পৃথক অধিবেশন চালানো হবে
  • প্রক্রিয়া সি অধিবেশন / প্রক্রিয়া গ্রুপ এপিআই ব্যবহার করতে পারে না কারণ এটি ভঙ্গুর সেটআপটি ভেঙে দেবে
  • এই জাতীয় প্রতিটি অপারেশনের জন্য একটি টার্মিনাল তৈরি করা এখন পর্যন্ত সেরা ধারণা নয়

0

যদিও 7 বছর পেরিয়ে গেছে আমি ঠিক এই সমস্যাটিতে চলে এসেছি কারণ আমি স্প্রিংবুট অ্যাপ্লিকেশনটি চালাচ্ছি যা বিকাশের সময় ওয়েবপ্যাক-ডেভ-সার্ভার শুরু করা দরকার এবং ব্যাকএন্ড প্রক্রিয়া বন্ধ হয়ে গেলে এটি হত্যা করা দরকার kill

আমি ব্যবহার করার চেষ্টা করি Runtime.getRuntime().addShutdownHookতবে এটি উইন্ডোজ 10 তে কাজ করেছে তবে উইন্ডোজ 7 এ নয়।

আমি এটি একটি উত্সর্গীকৃত থ্রেড ব্যবহার করতে পরিবর্তন করেছি যা প্রক্রিয়াটি ছাড়ার জন্য অপেক্ষা করে বা InterruptedExceptionযার জন্য উভয় উইন্ডোজ সংস্করণে সঠিকভাবে কাজ করে work

private void startWebpackDevServer() {
    String cmd = isWindows() ? "cmd /c gradlew webPackStart" : "gradlew webPackStart";
    logger.info("webpack dev-server " + cmd);

    Thread thread = new Thread(() -> {

        ProcessBuilder pb = new ProcessBuilder(cmd.split(" "));
        pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        pb.directory(new File("."));

        Process process = null;
        try {
            // Start the node process
            process = pb.start();

            // Wait for the node process to quit (blocking)
            process.waitFor();

            // Ensure the node process is killed
            process.destroyForcibly();
            System.setProperty(WEBPACK_SERVER_PROPERTY, "true");
        } catch (InterruptedException | IOException e) {
            // Ensure the node process is killed.
            // InterruptedException is thrown when the main process exit.
            logger.info("killing webpack dev-server", e);
            if (process != null) {
                process.destroyForcibly();
            }
        }

    });

    thread.start();
}

0

Orতিহাসিকভাবে, ইউএনআইএক্স ভি from থেকে, প্রক্রিয়া সিস্টেম একটি প্রক্রিয়াটির প্যারেন্ট আইডি পরীক্ষা করে প্রক্রিয়াগুলির অনাথতা সনাক্ত করেছে। যেমনটি আমি বলেছি, icallyতিহাসিকভাবে, init(8)সিস্টেম প্রক্রিয়াটি কেবল একটি কারণে বিশেষ প্রক্রিয়া: এটি মারা যায় না। এটি মারা যায় না কারণ নতুন প্যারেন্ট প্রসেস আইডি নির্ধারণের জন্য কার্নেল অ্যালগরিদম এই সত্যের উপর নির্ভর করে। যখন কোনও প্রক্রিয়া তার প্রক্রিয়া চালায় তখন সিস্টেম কলের আগে প্রক্রিয়াটি অনাথ হয়ে যায়।exit(2) কলটি (কোনও প্রক্রিয়া সিস্টেম কলের মাধ্যমে বা বাহ্যিক কার্য দ্বারা এটি একটি সিগন্যাল বা অনুরূপ প্রেরণ করে) কর্নেল এই প্রক্রিয়াটির সমস্ত বাচ্চাকে তাদের প্যারেন্ট প্রসেস আইডি হিসাবে পুনরায় নিযুক্ত করে। এটি সবচেয়ে সহজ পরীক্ষার দিকে পরিচালিত করে এবং কোনও প্রক্রিয়া অনাথ হয়েছে কিনা তা জানার সবচেয়ে বহনযোগ্য উপায়। কেবলমাত্র getppid(2)সিস্টেম কলের ফলাফল পরীক্ষা করুন এবং এটি যদি প্রক্রিয়া আইডি হয়init(2)

এই পদ্ধতির দুটি বিষয় উত্থাপিত হতে পারে যা সমস্যার দিকে নিয়ে যেতে পারে:

  • প্রথমত, আমাদের initযে কোনও ব্যবহারকারীর প্রক্রিয়াতে প্রক্রিয়াটি পরিবর্তনের সম্ভাবনা রয়েছে , সুতরাং আমরা কীভাবে আশ্বাস দিতে পারি যে আরম্ভ প্রক্রিয়া সর্বদা সমস্ত অনাথ প্রক্রিয়ার পিতা-মাতা হবে? ঠিক আছে, exitসিস্টেম কল কোডটিতে একটি স্পষ্ট চেক আছে কিনা তা দেখার জন্য যে কলটি সম্পাদনকারী প্রক্রিয়াটি আরম্ভ প্রক্রিয়া কিনা (পিড সমান পিড সমেত প্রক্রিয়া) কিনা এবং যদি এটি হয় তবে কার্নেল প্যানিক্স (এটি আর বজায় রাখতে সক্ষম হবে না) প্রক্রিয়া শ্রেণিবিন্যাস) সুতরাং এটি init প্রক্রিয়াটির জন্য কোনও exit(2)কল করার অনুমতি নেই ।
  • দ্বিতীয়ত, উপরে বর্ণিত বেসিক পরীক্ষায় একটি দৌড়ের শর্ত রয়েছে। আরিন প্রক্রিয়া আইডিটি historতিহাসিকভাবে থিম (8) be হিসাবে ধরে নেওয়া হয় , তবে আপনি নিরাপদে এই প্রক্রিয়াগুলির কোনও পিতা বা মাতা না থাকা হিসাবে ধরে নিতে পারেন (আপনি যখন কোনও সিস্টেমে আরম্ভের প্রক্রিয়াতে প্রতিস্থাপন করেন তখন বাদে)1 , তবে এটি পসিক্স পদ্ধতির দ্বারা আবশ্যক নয়, যা উল্লেখ করেছে (অন্যান্য প্রতিক্রিয়া হিসাবে প্রকাশিত হয়েছে) যে কেবলমাত্র কোনও সিস্টেমের প্রক্রিয়া আইডি সেই উদ্দেশ্যে সংরক্ষণ করা হয়েছে। প্রায় কোনও পোস্টিক্স বাস্তবায়ন এটি করে না এবং আপনি মূল ইউনিক্স উদ্ভূত সিস্টেমে ধরে নিতে পারেন যে সিস্টেম কলের 1প্রতিক্রিয়া হিসাবে getppid(2)প্রক্রিয়াটি অনাথকে ধরে নেওয়া যথেষ্ট। চেক করার আরেকটি উপায় হ'ল getppid(2)কাঁটাচামচের ঠিক পরে তৈরি করা এবং সেই মানটিকে একটি নতুন কলের ফলাফলের সাথে তুলনা করা। এটি কেবল সমস্ত ক্ষেত্রেই কার্যকর হয় না, কারণ উভয় কল একত্রে পারমাণবিক নয় fork(2)এবং প্রথম getppid(2)সিস্টেম কল করার আগে এবং তার আগে পিতামাতার প্রক্রিয়াটি মারা যেতে পারে । প্রক্রিয়া parent id only changes once, when its parent does anপ্রস্থান (2) call, so this should be enough to check if theগেটপিড (2)result changed between calls to see that parent process has exit. This test is not valid for the actual children of the init process, because they are always children of

-1

আমি সন্তানের পরিবেশ ব্যবহার করে প্যারেন্ট পিডটি পাস করেছি, পরে পর্যায়ক্রমে পরীক্ষা করা হয় / সন্তানের / পিপি / পিপিডের উপস্থিতি আছে কিনা।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.