【发布时间】:2015-10-29 06:39:58
【问题描述】:
我有一个System.Diagnostics.Process 的实例,它是通过Process.GetProcessesByName 创建的。
在我成功打开进程后,我会执行各种操作,例如读取它的内存和窗口标题。
这些操作是基于计时器不断执行的,我的意思是Timer.Elapsed事件处理程序是流程操作的来源。
现在,我注意到我有一个竞争条件,我无法使用我知道的任何东西来解决。它是这样发生的:
timerElapsedEvent(...) {
if (!process.HasExited) {
process.Refresh(); // Update title.
var title = process.MainWindowTitle;
}
}
如果进程正在运行,并且我的代码进入了if 块,那么进程在执行process.MainWindowTitle 调用之前退出的可能性很小,这会导致异常。
我需要一种方法来以某种方式捕获进程的退出事件并使其保持活动状态,直到可以安全地关闭它而不会使正在监视它的应用程序崩溃,从而确保它会等待@987654327 @ 关闭之前(或任何其他可以解决此问题的解决方案)。
此外,同时,另一个方法可能正在运行ReadProcessMemory,它也会崩溃。
我该如何解决这个问题?
PS:Process.Exit 事件处理程序不起作用,因为它不会在process.MainWindowTitle 之前触发,它只会在当前指令完成后触发。
我很确定以某种方式控制退出事件是解决此问题的唯一方法,因为 HasExit 可能随时更改,与在进程上实际调用方法之前我进行了多少检查无关。
PS2:我刚刚意识到这是一个 TOCTTOU 案例,除非我可以控制我打开的进程,否则这是无法解决的,所以我把它留在这里只是想看看是否有人知道这样做的方法。
【问题讨论】:
-
简单地捕获
InvalidOperationException并将其视为退出进程有什么问题?在处理外部进程时,存在各种根本无法解决的竞态条件;您的代码只需要准备好处理可能发生的错误。 -
嘿,彼得!捕获异常没有什么问题,我只是想确保没有办法同步线程或其他东西,没有解决方案。
-
无论你做什么(在合理范围内......如果你准备好对系统进行rootkit并接管Windows内核,我想你可以做任何你想做的事情:)),这个过程可以在没有任何同步的可能性的情况下被杀死。正如一个人必须随时准备好捕捉
FileNotFoundException,即使在刚刚看到File.Exists()返回true之后,您自己的代码也需要始终准备好让进程退出,即使Process.HasExited属性刚刚返回@ 987654335@. -
我 100% 同意你的推理。 Process.HasExited 会返回 false,而不是 true 8P
-
我认为这不是线程问题。一定只是本机调用失败(或者我错过了处理此问题的托管代码中的某些内容,尽管我很确定我没有)。我做了一个快速测试并确认即使
EnableRaisingEvents未设置true也会发生异常。所以,是的,你有 TOCTTOU,除了准备捕捉异常之外,你真的无能为力。就像我之前提到的,由于操作系统总是可以直接杀死进程,即使你可以接管进程并控制它,你仍然无法确保不会出现异常。
标签: c# process synchronization race-condition