Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>2005-09-21 09:49:59 +0400
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>2005-09-21 09:49:59 +0400
commit10875ea704d128ce9486a5e0e8a98552efd75d64 (patch)
treef8915db6555142ddebd32211b86916142bb21395 /mcs/class/System/System.Diagnostics/Process.cs
parented6bbe092b40917ff53bd9a4de54bf9cde51c0c9 (diff)
2005-09-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* Process.cs: deal with the fact that someone can enable raising events and/or registed a Exited delegate before and *after* Start is called for the process. Only queue the exit callback in the threadpool when it's possible and requested. Fixes bug #76129. svn path=/trunk/mcs/; revision=50356
Diffstat (limited to 'mcs/class/System/System.Diagnostics/Process.cs')
-rw-r--r--mcs/class/System/System.Diagnostics/Process.cs55
1 files changed, 40 insertions, 15 deletions
diff --git a/mcs/class/System/System.Diagnostics/Process.cs b/mcs/class/System/System.Diagnostics/Process.cs
index 86ed56acb1b..b9848b6b279 100644
--- a/mcs/class/System/System.Diagnostics/Process.cs
+++ b/mcs/class/System/System.Diagnostics/Process.cs
@@ -66,7 +66,9 @@ namespace System.Diagnostics {
IntPtr process_handle;
int pid;
bool enableRaisingEvents;
+ bool already_waiting;
ISynchronizeInvoke synchronizingObject;
+ EventHandler exited_event;
/* Private constructor called from other methods */
private Process(IntPtr handle, int id) {
@@ -74,8 +76,8 @@ namespace System.Diagnostics {
pid=id;
}
- [MonoTODO]
- public Process() {
+ public Process ()
+ {
}
[MonoTODO]
@@ -87,6 +89,17 @@ namespace System.Diagnostics {
}
}
+ void StartExitCallbackIfNeeded ()
+ {
+ bool start = (!already_waiting && enableRaisingEvents && exited_event != null);
+ if (start && process_handle != IntPtr.Zero && !HasExited) {
+ WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
+ ProcessWaitHandle h = new ProcessWaitHandle (process_handle);
+ ThreadPool.RegisterWaitForSingleObject (h, cb, this, -1, true);
+ already_waiting = true;
+ }
+ }
+
[DefaultValue (false), Browsable (false)]
[MonitoringDescription ("Check for exiting of the process to raise the apropriate event.")]
public bool EnableRaisingEvents {
@@ -94,9 +107,8 @@ namespace System.Diagnostics {
return enableRaisingEvents;
}
set {
- if (process_handle != IntPtr.Zero)
- throw new InvalidOperationException ("The process is already started.");
-
+ if (value && !enableRaisingEvents)
+ StartExitCallbackIfNeeded ();
enableRaisingEvents = value;
}
@@ -820,12 +832,6 @@ namespace System.Diagnostics {
throw new Win32Exception (-proc_info.pid);
}
- if (process.enableRaisingEvents && process.Exited != null) {
- WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
- ProcessWaitHandle h = new ProcessWaitHandle (proc_info.process_handle);
- ThreadPool.RegisterWaitForSingleObject (h, cb, process, -1, true);
- }
-
process.process_handle=proc_info.process_handle;
process.pid=proc_info.pid;
@@ -845,6 +851,8 @@ namespace System.Diagnostics {
process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
}
+ process.StartExitCallbackIfNeeded ();
+
return(ret);
}
@@ -913,7 +921,20 @@ namespace System.Diagnostics {
[Category ("Behavior")]
[MonitoringDescription ("Raised when this process exits.")]
- public event EventHandler Exited;
+ public event EventHandler Exited {
+ add {
+ if (process_handle != IntPtr.Zero && HasExited) {
+ value.BeginInvoke (null, null, null, null);
+ } else {
+ exited_event = (EventHandler) Delegate.Combine (exited_event, value);
+ if (exited_event != null)
+ StartExitCallbackIfNeeded ();
+ }
+ }
+ remove {
+ exited_event = (EventHandler) Delegate.Remove (exited_event, value);
+ }
+ }
// Closes the system process handle
[MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -967,16 +988,20 @@ namespace System.Diagnostics {
protected void OnExited()
{
- if (Exited == null)
+ if (exited_event == null)
return;
if (synchronizingObject == null) {
- Exited (this, EventArgs.Empty);
+ foreach (EventHandler d in exited_event.GetInvocationList ()) {
+ try {
+ d (this, EventArgs.Empty);
+ } catch {}
+ }
return;
}
object [] args = new object [] {this, EventArgs.Empty};
- synchronizingObject.BeginInvoke (Exited, args);
+ synchronizingObject.BeginInvoke (exited_event, args);
}
class ProcessWaitHandle : WaitHandle