做了一个运行程序,然后等待程序结束的函数,大体流程如下:

伪代码:
CreateProcess(...) -> processHandle;
...
WaitForSingleObject(processHandle);

发现CreateProcess创建的进程已经结束了,但WaitForSingleObject还一直在等待。

更加诡异的是,这个问题在Release里没有发生,在Debug里就发生了!

查MSDN:https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject

后发现了问题:

Parameters

hHandle

A handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.

If this handle is closed while the wait is still pending, the function's behavior is undefined.

The handle must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.

注意到红色的字没有,大体意思是如果在WaitFor的过程中等待的句柄被关闭了,则WaitFor则会出现各种未知错误。再结合只在Debug的情况下发生,我即刻想到了这种情况:

CreateProcess -->  进程结束了  -->   WaitFor

注意进程结束了吧,进程结束后processHandle就不可能改变状态了,也就是随后给的WaitFor传入的Handle不可能改变状态了,所以WaitFor就会一直等下去。

搞清楚问题所在,把过程改为:创建一个线程监听进程IO,程序结束后,IO结束,再配合waitFor event,就可以解决问题了。

最后附上我的创建进程的函数:

unsigned __stdcall _Execute_readAndWrite(void* arg)
{std::tuple<HANDLE, std::string*, HANDLE>* tpParams = (std::tuple<HANDLE, std::string*, HANDLE>*)arg;HANDLE hRead = std::get<0>(*tpParams);std::string* sPrintText = std::get<1>(*tpParams);HANDLE ev = std::get<2>(*tpParams);//读取命令行返回值char buff[1024 + 1];DWORD dwRead = 0;while (ReadFile(hRead, buff, 1024, &dwRead, NULL)){if (sPrintText){buff[dwRead] = '\0';sPrintText->append(buff, dwRead);}}SetEvent(ev);return 0;
}bool Execute(const char* szFile, const char* szParam, unsigned long& exitCode, std::string* sPrintText = NULL, unsigned long timeout = 0)
{if (!szFile || szFile[0] == '\0')return false;HANDLE hRead, hWrite;//创建匿名管道SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };if (!CreatePipe(&hRead, &hWrite, &sa, 0)){return false;}int nCmdLen = (strlen(szFile) + strlen(szParam) + 4) * sizeof(char);char* szCmd = (char*)_alloca(nCmdLen);//_alloca在栈上申请的,会自动释放memset(szCmd, 0, nCmdLen);strcpy(szCmd, "\"");strcat(szCmd, szFile);strcat(szCmd, "\"");if (szParam){strcat(szCmd, " ");strcat(szCmd, szParam);}//设置命令行进程启动信息(以隐藏方式启动命令并定位其输出到hWrite)STARTUPINFOA si = { sizeof(STARTUPINFOA) };GetStartupInfoA(&si);si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;si.wShowWindow = SW_NORMAL;si.hStdError = hWrite;si.hStdOutput = hWrite;//启动命令行PROCESS_INFORMATION pi;if (!CreateProcessA(NULL, (char *)szCmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)){CloseHandle(hWrite);CloseHandle(hRead);return false;}//立即关闭hWriteCloseHandle(hWrite);HANDLE ev = CreateEventA(NULL, TRUE, FALSE, NULL);bool bRet = true;unsigned int uiThreadID = 0;HANDLE hThreadRW = (HANDLE)_beginthreadex(NULL, 0, _Execute_readAndWrite, (void*)&(std::tuple<HANDLE, std::string*, HANDLE>(hRead, sPrintText, ev)), 0, &uiThreadID);DWORD waitRet = 0;if (timeout > 0)waitRet = WaitForSingleObject(ev, timeout);elsewaitRet = WaitForSingleObject(ev, INFINITE);switch (waitRet){case WAIT_TIMEOUT:case WAIT_FAILED:TerminateThread(hThreadRW, 1);TerminateProcess(pi.hProcess, 1);bRet = false;break;case WAIT_OBJECT_0:       GetExitCodeProcess(pi.hProcess, &exitCode);//获得返回值bRet = true;break;}CloseHandle(hRead);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);CloseHandle(ev);return bRet;
}

WaitForSingleObject、WaitForMultipleObjects假死,永远等待的问题相关推荐

  1. Java线上问题排障:Linux内核bug引发JVM死锁导致线程假死

    Java本质上还是离不开操作系统,一来Java源码是用C/C++实现的,二来java进程还是需要依附于操作系统和硬件资源,有时候一些问题是操作系统级别导致的,下面的整个事件是源自一则真实的线上案例. ...

  2. 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死...

    .c# Invoke和BeginInvoke 区别 Control.Invoke 方法 (Delegate):在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke ...

  3. C# Application.DoEvents() 处理队列消息,防界面假死。

    该方法可以处理当前队列的消息,比如一个for循环 5000次 向TextBox中追加文本,那肯定会假死一会儿的. 此时便可使用Application.DoEvents()来处理队列的信息. 简单说下使 ...

  4. java启动子线程过多导致卡死_java线程基础巩固---多Product多Consumer之间的通讯导致出现程序假死的原因分析...

    在上一次中已经实现一个生产者与消费者的初步模型(http://www.cnblogs.com/webor2006/p/8413286.html),但是当时只是一个生产者对应一个消费者,先贴下代码: p ...

  5. 转:优化js脚本设计,防止浏览器假死

    原链接打不开了,复制一份保存: 在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出"脚本运行时间过长"的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化 ...

  6. linux进程假死的原因_一次Spring Boot假死诊断

    这两天遇到一个服务假死的问题,具体现象就是服务不再接收任何请求,客户端会抛出Broken Pipe. 01 检查系统状态 执行top,发现CPU和内存占用都不高,但是通过命令 netstat -n | ...

  7. 鼠标右键转圈圈_鼠标右键文件夹出现转圈圈假死机情况

    问题描述: 2018年10月13日发现该问题,桌面除Administrator.计算机.回收站右键完好,其他任何文件都出现转圈圈假死机问题. 开始菜单-所有程序里文件.计算机硬盘内文件均出现此问题. ...

  8. java假死_分析java进程假死

    一.引言 1.编写目的 为了方便大家以后发现进程假死的时候能够正常的分析并且第一时间保留现场快照. 2.编写背景 最近服务器发现tomcat的应用会偶尔出现无法访问的情况.经过一段时间的观察最近又发现 ...

  9. 谈.Net委托与线程——解决窗体假死

    转自:http://www.cnblogs.com/smartls/archive/2011/04/08/2008981.html#2457370 引言 在之前的<创建无阻塞的异步调用>中 ...

  10. Ubuntu下安装Wine可能导致假死问题解决方案

    Ubuntu下安装Wine可能导致假死问题解决方案 出现问题 在使用Ubuntu使用apt-get install wine时,导致下载处于假死状态,不论将dpkg命令杀死,还是按照提示sudo ap ...

最新文章

  1. 初入职场的我怎么就成了个打杂的,我是这样破局的 No.146
  2. 浅析 Linux 初始化 init 系统:sysvinit
  3. 阿帕奇跨域_阿帕奇光束
  4. 方法参数名称和Spring
  5. maven ssm框架 mysql_SSM框架(IDEA+Spring+SpringMVC+Maven+Mybatis+MySQL)
  6. Kafka单节点多broker的部署和使用
  7. c#实现http文件下载
  8. python的优点有哪些-Python为何这么火,究竟有哪些优势?
  9. template 不能分别在.h和.cpp中定义模板
  10. 使用 Jupyter Notebook
  11. win10打开无线网卡服务器,win10打不开无线网卡
  12. 债居时代总结与读后感——房贷如何影响经济[美]阿蒂夫·迈恩 [美]阿米尔·苏非著
  13. mac清理软件哪个好用?五大Mac Cleaner介绍推荐
  14. 智能停车场车牌识别计费系统
  15. linux中如何看文件换行符,linux下的换行符
  16. 360兼容性问题:教资报名请使用搜狗浏览器(兼容模式)、360浏览器(兼容模式)、QQ浏览器(内核模式请选择:总是使用IE内核)、IE系列浏览器。
  17. 冬日舞会服务器维护中,绝版皮肤被天美终结,冬日舞会太优雅?宫本很可惜,这款没见过!...
  18. 利用js制作一个简单的QQ农场小游戏
  19. 红米路由器ac2100怎样设置ipv6_【路由刷机】红米小米 AC2100 Windows下刷Padavan固件小小白教程、升级固件...
  20. 关于百度云推送加厂商进行app离线推送的步骤小记

热门文章

  1. 常见的各种人提出的理论
  2. 共享单车项目(一)--项目简介
  3. excel两列数据对比找不同_眼睛的救星,Excel怎么快速找出两列数据的不同之处?...
  4. 怎么做超链接html,HTML怎么做超链接
  5. windows系统笔记本连接外部显示器进行分屏
  6. 【实验技术笔记】基因沉默:siRNA/shRNA
  7. 以太坊的 ChainId 与 NetworkId
  8. 【金融基础设施建设01】金融基础设施建设概论(金融基础设施的定义、现状、国内外标准、基本特征、作用、风险)
  9. VB6+Mo图层顺序的调整(MoveToTop、MoveTo、MoveToBottom )
  10. java 合并excel单元格