我有一份工作,定期执行一些涉及ServerXmlHttpRquest
的工作来执行HTTP POST
。这项工作每60秒运行一次。
通常它没有问题。但是大约有五分之一的机会(每两三个月)它会挂起:
IXMLHttpRequest http = new ServerXmlHttpRequest();
http.open("POST", deleteUrl, false, "", "");
http.send(stuffToDelete); <---hang
当它挂起时,甚至任务计划程序(如果运行时间超过3分钟,启用了杀死作业的选项)都可以结束任务。我必须连接到远程客户的网络,进入服务器,并使用任务管理器来终止进程。
然后再过一个月或三个月。
最终我开始使用任务管理器创建进程转储
所以我可以分析挂起的位置。经过五次崩溃后(过去11个月左右),我得到了一致的图片:
ntdll.dll!_NtWaitForMultipleObjects@20()
KERNELBASE.dll!_WaitForMultipleObjectsEx@20()
user32.dll!MsgWaitForMultipleObjectsEx()
user32.dll!_MsgWaitForMultipleObjects@20()
urlmon.dll!CTransaction::CompleteOperation(int fNested) Line 2496
urlmon.dll!CTransaction::StartEx(IUri * pIUri, IInternetProtocolSink * pOInetProtSink, IInternetBindInfo * pOInetBindInfo, unsigned long grfOptions, unsigned long dwReserved) Line 4453 C++
urlmon.dll!CTransaction::Start(const wchar_t * pwzURL, IInternetProtocolSink * pOInetProtSink, IInternetBindInfo * pOInetBindInfo, unsigned long grfOptions, unsigned long dwReserved) Line 4515 C++
msxml3.dll!URLMONRequest::send()
msxml3.dll!XMLHttp::send()
Contoso.exe!FrobImporter.TFrobImporter.DeleteFrobs Line 971
Contoso.exe!FrobImporter.TFrobImporter.ImportCore Line 1583
Contoso.exe!FrobImporter.TFrobImporter.RunImport Line 1070
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.HandleFrobImport Line 433
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.CoreExecute Line 71
Contoso.exe!CommandLineProcessor.TCommandLineProcessor.Execute Line 84
Contoso.exe!Contoso.Contoso Line 167
kernel32.dll!@BaseThreadInitThunk@12()
ntdll.dll!__RtlUserThreadStart()
ntdll.dll!__RtlUserThreadStart@8()
所以我做了ServerXmlHttpRequest.send
,它永远不会回来。它将在那里呆上几天(导致系统错过金融交易,直到周日晚上我接到一个电话,它已经坏了)。
除非有人知道如何调试代码,否则没有任何帮助,但转储时陷入停顿的线程中的寄存器是:
EAX 00000030
EBX 00000000
ECX 00000000
EDX 00000000
ESI 002CAC08
EDI 00000001
EIP 732A08A7
ESP 0018F684
EBP 0018F6C8
EFL 00000000
您可以使用serverXmlHttpRequest.setTimeouts(...)
配置四类超时:
KB305053(决定保持连接打开的服务器将导致serverXmlHttpRequest等待连接关闭)似乎可能是问题。但是30秒的默认超时会解决这个问题。
Windows任务计划程序无法终止任务;即使该选项已启用即可。
我将研究使用Windows Job API将 self 进程添加到作业,并使用SetInformationJobObject
为我的进程设置时间限制:
将我的流程限制为三分钟的执行时间:
PerProcessUserTimeLimit
如果 LimitFlags 指定 JOB_OBJECT_LIMIT_PROCESS_TIME ,此成员是每个进程 用户模式执行时间限制,以100纳秒为单位。除此以外, 该成员被忽略。系统会定期检查以确定 与工作相关的每个流程是否累积得更多 用户模式时间超过设置限制。如果有,那么过程是 终止。
如果作业是嵌套的,则有效限制最多 工作链中的限制性限制。
虽然由于Task Scheduler使用Job对象也限制了任务的时间,但我并不希望Job Object可以限制作业。
修改:作业对象无法按处理时间限制流程 - 仅限用户时间。并且当一个进程空闲等待一个对象时,它不会累积任何用户时间 - 当然不会超过三分钟。
答案 0 :(得分:1)
考虑切换到更新的受支持API。
MSXML2.ServerXMLHTTP.6.0
WinHttp.WinHttpRequest.5.1
。不再支持msxml3.dll库,仅出于兼容性原因而保留。另外,msxml4.dll(和更新版本)中包含了许多security and stability improvements,你错过了这些内容。