進程已不存在,但端口仍被占用


問題現象:

進程SA已經結束, 但其守護進程Daemon卻始終無法connect SA. 在connect(port)時出錯. 使用telnet 127.0.0.1 9090 也無法連接上SA的端口. 使用TcpView查看進程與端口對應關系, 發現9090端口仍被占用, 但對應的進程卻是[non-existent].

原因:

經查, 該問題出現的原因, 是由於SA進程已經結束了, 但經由SA產生的某些子進程卻還未結束,資源還未完全釋放,導致端口仍被占用.

解決:

1. 經查, SA結束后, 其所啟動的winamp, 在SA主進程Run()結束的時候, 並沒有被kill掉. 結束winamp進程.

2. 修改winamp后,本以為問題會解決,但是該問題仍重現了. 再次調查,使用 Process Explorer查看進程, 發現有幾個"cmd.exe"進程是由SA啟動的(將鼠標放在進程上, 彈出的懸浮窗口所顯示的信息可看到該cmd是由SA所啟動的), 這幾個"cmd.exe"進程在SA結束后,並沒有被關閉.

strCmd.Format("rd %s /s /q", strWorkDirectory);
::system(strCmd);

上面代碼的目的是remove directory(rd). system()函數,會默認啟動cmd.exe.

為解決此問題, 需要將SA所啟動的"cmd.exe"結束掉. 但是其他進程也有啟動"cmd.exe", 包括系統進程. 他們所啟動額"cmd.exe"不能被kill掉. 

解決辦法是: 遍歷進程, 如果遇見"cmd.exe", 則判斷它的父進程是否存在,如果存在,不作處理,如果不存在,則將該"cmd.exe" kill掉.

int ProcessStatus(UINT uPid)
{
    HANDLE hProcessSnap;
    HANDLE hProcess;
    PROCESSENTRY32 pe32;

    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if( hProcessSnap == INVALID_HANDLE_VALUE ) 
    {
        return -1;
    }

    // Set the size of the structure before using it.
    pe32.dwSize = sizeof( PROCESSENTRY32 );

    // Retrieve information about the first process,
    // and exit if unsuccessful
    if( !Process32First( hProcessSnap, &pe32 ) )
    {
        CloseHandle( hProcessSnap );          // clean the snapshot object
        return -1;
    }
    do
    {
        if(pe32.th32ProcessID == uPid) return 1;
    } while( Process32Next( hProcessSnap, &pe32 ) );

    CloseHandle( hProcessSnap );
    return 0;
}

void KillProcessByPid(UINT uPid)
{
    CString strCmd;
    strCmd.Format("taskkill /f /pid %u", uPid);
    ::system(strCmd);
}

void KillExistentProcess()
{
    HANDLE hProcessSnap;
    HANDLE hProcess;
    PROCESSENTRY32 pe32;

    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if( hProcessSnap == INVALID_HANDLE_VALUE ) 
    {
        return;
    }

    // Set the size of the structure before using it.
    pe32.dwSize = sizeof( PROCESSENTRY32 );

    // Retrieve information about the first process,
    // and exit if unsuccessful
    if( !Process32First( hProcessSnap, &pe32 ) )
    {
        CloseHandle( hProcessSnap );          // clean the snapshot object
        return;
    }
    do
    {
        char *pImageName = pe32.szExeFile;
        if(strcmp("cmd.exe", pImageName) == 0) {
            int nStatus = ProcessStatus(pe32.th32ParentProcessID);
            if (nStatus == 0) { // If parent process doesn't exist
                KillProcessByPid(pe32.th32ProcessID);            
            }
        }
    } while( Process32Next( hProcessSnap, &pe32 ) );

    CloseHandle( hProcessSnap );
}

參考:

How do I kill a process that is dead but listening? (http://superuser.com/questions/215351/how-do-i-kill-a-process-that-is-dead-but-listening)
How do you free up a port being held open by dead process? (http://serverfault.com/questions/181015/how-do-you-free-up-a-port-being-held-open-by-dead-process/273727#273727)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM