Pete,
now here's the final one:
If you enable the interrupts ( //p.EnableRaisingEvents = false; in line 43 -
ShellKill() ) you will get eventing as expected (separate thredas, nice halt
on semaphore, proper sequencing):
ShellKill - Thread 10
ShellKill - Got lock - go for kill
OnExited - Thread 14 - go for lock
ShellKill - CMD killed - wait here for event to happen
ShellKill - back from sleep - releasing lock
OnExited - inside lock
OnExited - released lock
ShellKill - lock released
Press CR to exit
If you enable this line you will surprisingly (undesiredly) still get an
event firing (hmm??), but the event will be in the same thread context and
logically deadlock itself.
Now I am curious what the real issue is!
Thanks again for sticking with this!
br
Theo
------
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Net;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using System.Collections;
namespace Deadlock
{
class Deadlock : MarshalByRefObject
{
static Deadlock d = null;
static Process p;
static int Main(string[] args)
{
d = new Deadlock();
if (args.Length == 1 && args[0] == "-h") return d.RunServer();
d.ShellStart();
Console.WriteLine("Press CR to start kill shell process");
Console.ReadLine();
d.ShellKill();
Console.WriteLine("Press CR to exit");
Console.ReadLine();
return 0;
}
Semaphore s = new Semaphore(1, 1);
HttpChannel httpchnl = null;
private void ShellKill()
{
Console.WriteLine("ShellKill - Thread " +
Thread.CurrentThread.ManagedThreadId);
s.WaitOne();
Console.WriteLine("ShellKill - Got lock - go for kill");
//comment line out and this will work
p.EnableRaisingEvents = false;
if (p == null)
{
Console.WriteLine("ShellKill : Shell exited already");
}
else
{
try
{
if ((httpchnl =
(HttpChannel)ChannelServices.GetChannel("http")) == null)
{
IDictionary props = new Hashtable();
props["timeout"] = "10000"; //in ms
httpchnl = new HttpChannel(
props,
new SoapClientFormatterSinkProvider(),
null
);
ChannelServices.RegisterChannel(httpchnl, false);
}
//remote invoke exit on the remote server - also causes
shell to exit
Deadlock d = (Deadlock)Activator.GetObject(
typeof(Deadlock),
@"
http://localhost:8085/dl");
d.ShutdownServer();
}
catch (WebException) { }
if (!p.HasExited) p.Kill();
Console.WriteLine("ShellKill - CMD killed - wait here for
event to happen");
//simulate some other cleanup work
Thread.Sleep(2000);
p = null;
Console.WriteLine("ShellKill - back from sleep - releasing
lock");
}
s.Release();
Console.WriteLine("ShellKill - lock released");
}
private void ShellStart()
{
//string arg = @"z1 c:/Programme/AmiBroker/abm/abm.exe -h";
string arg = "cmd /c Deadlock.exe -h";
//string arg = "z1 cmd.exe /c pause";
//string arg = "/c pause";
ProcessStartInfo psi = new ProcessStartInfo("cmd", arg);
p = new Process();
p.StartInfo = psi;
p.Exited += new EventHandler(OnExited);
p.EnableRaisingEvents = true;
p.Start();
}
void OnExited(object sender, EventArgs e)
{
Console.WriteLine("OnExited - Thread " +
Thread.CurrentThread.ManagedThreadId + " - go for lock");
s.WaitOne();
Console.WriteLine("OnExited - inside lock");
//dispose process (and other resources)
p = null;
s.Release();
Console.WriteLine("OnExited - released lock");
}
private HttpServerChannel httpserverchannel = null;
private static Thread server = null;
public int RunServer()
{
server = Thread.CurrentThread;
Console.WriteLine("Server Channel registration");
httpserverchannel = new HttpServerChannel(8085);
ChannelServices.RegisterChannel(httpserverchannel, false);
//Register TYPE:
Console.WriteLine("Type registration");
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(Deadlock),
"dl",
WellKnownObjectMode.Singleton
);
try
{
Console.WriteLine("Server started and listening on
http(8085).");
Console.WriteLine("Main Server ThreadId " +
Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Start time: {0}",
System.DateTime.Now.ToString());
Console.WriteLine("Server " + System.Environment.MachineName
+ " running");
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
Console.WriteLine("Server released by Exception");
Console.WriteLine(e.Message);
}
Console.WriteLine("\nEnd time: {0}",
System.DateTime.Now.ToString());
Thread.Sleep(5000);
return 0;
}
public int ShutdownServer()
{
Console.WriteLine("Shutdown signal received from client");
server.Interrupt();
server.Join();
return 0;
}
}
}