程序中解决Windows服务器下进程不存在但端口被占用问题

程序中解决Windows服务器下进程不存在但端口被占用问题

问题现象:

1、使用命令netstat -ano | findstr 端口查看端口占用进程,会得到端口占用进程的PID号,但通过PID号在任务管理器中查不到该进程,且使用命令taskkill /f /pid PID号时报错没有找到进程;
2、使用Process Explorer工具搜索PID号会发现进程中存在一cmd.exe子进程;
3、若此时在任务管理器中或cmd命令中杀死该cmd.exe进程,会发现原占用端口被释放。

问题原因:

程序停止时调用了system()函数,而此函数会启动cmd.exe程序执行系统命令,在某些异常情况(也可能系统本身问题)下,会出现原程序已被停止释放,但cmd子进程迟迟未被回收,导致原程序占用端口未被释放。

程序修改方法:

可以通过父子进程的关系进行优化解决,虽然系统其它进程也会调用cmd.exe进程,但正常情况下它们父子关系是存在的。在如上问题中,cmd.exe进程的父进程已不存在,故可以将其看做是异常泄漏进程。那么,我们在启动程序服务前只需让程序遍历目前服务器中所有的进程,找到不存在父子关系的cmd.exe进程,将其先行杀死,这样既可避免因异常cmd进程占用程序端口导致程序无法启动的问题。

#include <Tlhelp32.h>
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)
{
	char strCmd[50]={0};
	_snprintf(strCmd, 49, "taskkill /f /t /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 );
}

void StartSvr()
{
	KillExistentProcess();
	…	
	…
	…
}

参考:https://www.cnblogs.com/zhcncn/archive/2013/02/04/2891489.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章