リサイクルされたPIDを処理するときは、PIDのプロセスが有効になっていることを確認してください。

リサイクルされたPIDを処理するときは、PIDのプロセスが有効になっていることを確認してください。

私がオンラインで見たところによると、C ++でkillメソッドを呼び出して、プロセスがまだ生きていることを確認します。問題は、PIDが循環していて、探している同じPIDが同じプロセスではない可能性があることです。お互いの子ではなく、2つのプロセスを持つプログラムがあります。それらと通信できる唯一の方法はIPCです。クライアントプロセスが終了したら、私のホストプロセスも終了したいと思います。これを行うには、クライアントのプロセスがもう存在しない時期を知る必要があります。

Windowsには、ハンドルを作成したプロセスが閉じられるまでPIDがリサイクルされないようにする、いわゆるプロセスハンドラがあります。 macOS / Linux(POSIX)システムでこれを実装する方法を知りたいです。

問題のコードはPIDにリサイクルされます。

if (0 == kill(pid, 0))
{
    // Process exists.
}

答え1

私がオンラインで見たところによると、C ++でkillメソッドを呼び出して、プロセスがまだ生きていることを確認します。問題は、PIDがループしていて、探している同じPIDが同じプロセスではない可能性があることです。

はい。したがって、このkillアプローチはいいえ働く実際、物語はここで終わります。効果的なツールではありません。

2つのオプション:

  • 監視しているプロセスが自分の子プロセス(または自分のプロセスグループ内のプロセス)である場合は、waitpid特に終了時点を監視してください。
  • プロセスが次のような場合いいえ子プロセスに関して、POSIX「理想的」は、自分のプロセスが必ずしもそのプロセスのライフサイクルと密接にやり取りする必要はないと言います(少なくともこれがwaitpid制限から下された結論です)。 「追跡」権限を持ち、それを使用して他のptraceプロセスに接続し、exit呼び出しを待つことができます。

答え2

解決策はPIDを保持窓に通ってください隠れ家システムprocess handleの場合は、単に起動します。POSIXコア OS DEPENDANT!次に、キャッシュされた開始時間が現在の開始時間と同じであることを確認してください。 PID 衝突が検出されない場合は false が返されます。

Windows:

#include <windows.h>
#include <iostream>
#include <vector>
#include <map>

map<DWORD, HANDLE> handles;
bool isProcessAlive(DWORD pid)
{
    HANDLE process;
    if(handles.find(pid) == handles.end())
    {
        process = OpenProcess(SYNCHRONIZE, FALSE, pid);
        handles[pid] = process;
    }
    else
    {
        process = handles[pid];
    }
    DWORD ret = WaitForSingleObject(process, 0);
    bool isRunning = ret == WAIT_TIMEOUT;
    if(!isRunning)//close the cached handle to free the PID and erase from the cache
    {
        CloseHandle(process);
        handles.erase(pid);
    }
    return isRunning;
}

アップルシステム:

#include <signal.h>
#include <stddef.h>
#include <sys/_types/_timeval.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
/**
 * map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
 */
std::map<unsigned long, string> handles;
/**
 * returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
 */
bool isProcessAlive(unsigned long pid)
{
    // Get process info from kernel
    struct kinfo_proc info;
    int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
    size_t len = sizeof info;
    memset(&info,0,len);
    int rc = sysctl(mib, (sizeof(mib)/sizeof(int)), &info, &len, NULL, 0);

    //exit program sysctl failed to verify PID
    if (rc != 0)
    {
        handles.erase(pid);
        return false;
    }

    //extract start time and confirm PID start time equals org start time
    struct timeval tv = info.kp_proc.p_starttime;
    if(tv.tv_sec == 0)
    {
        handles.erase(pid);
        return false;
    }
    string time = to_string(tv.tv_usec) + "-" + to_string(tv.tv_sec);
    if(handles.find(pid) != handles.end())
    {
        string org_time = handles[pid];
        if(org_time != time)
        {
            cout << "PID Conflict PID:" << pid << " org_time:" + org_time << " new_time:" << time << endl;
            handles.erase(pid);
            return false;
        }
    }
    else
    {
        handles[pid] = time;
    }
    return true;
}

Linux:

#include <iostream>
#include <vector>
#include <map>
#include <signal.h>
#include <dirent.h>
#include <errno.h>
#include <fstream>

#include <iostream>
#include <iterator>
#include <sstream>
#include <fstream>
#include <vector>
#include <cstring>
#include <cerrno>
#include <ctime>
#include <cstdio>
#include <fcntl.h>
#include <sys/time.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
#include "/usr/include/x86_64-linux-gnu/sys/param.h"

/**
 * map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
 */
std::map<unsigned long, string> handles = {};
/**
 * returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
 */
bool isProcessAlive(unsigned long pid)
{
    ifstream procFile;
    string f = "/proc/"+ std::to_string(pid)+ "/stat";
    procFile.open(f.c_str());
    if(!procFile.fail())
    {
        //get creation time of current pid's process
        char str[255];
        procFile.getline(str, 255);  // delim defaults to '\n'

        vector<string> tmp;
        istringstream iss(str);
        copy(istream_iterator<string>(iss),
             istream_iterator<string>(),
             back_inserter<vector<string> >(tmp));

        string creation_time = tmp.at(21);

        //check if the process's creation time matches the cached creation time
        if(handles.find(pid) != handles.end())
        {
            string org = handles[pid];
            //if the pid's creation time is not the cached creation time we assume it's not the same process and the original has closed
            //unlike java the ==,!= actually checks .equals() when comparing
            if(creation_time != org)
            {
                std::cerr << "PID conflict:" + to_string(pid) + " orgCreationTime:" + org + " newCreationTime:" + creation_time;
                handles.erase(pid);
                procFile.close();
                return false;
            }
        }
        handles[pid] = creation_time;
        procFile.close();
        return true;
    }
    handles.erase(pid);
    procFile.close();
    return false;
}

関連情報