threading problem; dot net bug or me? (test case included)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David

    threading problem; dot net bug or me? (test case included)

    I've written a small windows service, and I'm having a problem that I'm
    spending a lot more time on than I'd like.
    If anyone has experienced this problem and has any hints or solutions; they
    would be appreciated.

    Simply leaving the threadMain() method if something unexpected occurs during
    thread execution leaves the thread in a ThreadState.Run ning state. This
    (apparently??) causes the Thread.Join() in service.OnStop( ) to hang
    indefinitely, resulting in a service that can't be stopped. A
    Thread.Sleep(0) in threadMain() yields the same result. So I thought I'd ask
    the service to stop from the thread and then just hang around, waiting for a
    regular service shutdown. ServiceControll er.Stop() does seem to run
    asynchronously, so no obvious problems to this, except that it always hangs
    on the instruction setting the field ThreadCodeClass .dieNow.

    As for dieNow, I've tried using a lock(this) section in a property instead
    of the volatile field. Didn't work either.
    Tried compiling against v1.0.3705 and v1.1.4322, same result.

    ===== Source code =====
    using System;
    using System.IO;
    using System.ServiceP rocess;
    using System.Threadin g;

    namespace Dummy {

    public class Debug {
    private static StreamWriter sw;

    public static void log(string s) {
    if (sw == null) {
    sw = File.AppendText ("c:\\lagkage.t xt");
    sw.AutoFlush = true;
    sw.Write("\r\n\ r\n--- Test run at " + DateTime.Now + " ---\r\n\r\n");
    }
    // no thread safety information in the .net docs on System.IO.File;
    locking just to be sure
    lock(sw) {
    sw.Write("" + DateTime.Now.To String("yyyy-MM-dd HH:mm:ss.ffffff f "));
    sw.WriteLine(s) ;
    }
    }
    }

    public class ThreadCodeClass {
    public volatile bool dieNow = false;

    public void threadMain() {
    Debug.log("Thre ad: started.");
    try {
    while (! dieNow) {
    Debug.log("Thre ad: running.");
    // code that does one thing or the other would be here
    throw new Exception("wak wak simulated failure");
    Thread.Sleep(50 00);
    }
    } catch (Exception e) {
    Debug.log("Thre ad: Unexpected exception occured; I don't know how to
    handle this. This is fatal; attempting automated service shutdown. Exception
    was: " + e.Message);
    try {
    ServiceControll er sc = new ServiceControll er(TestService. serviceName);
    // Assuming this is done asynchronously - the .net docs doesn't mention
    sc.Stop();
    Debug.log("Thre ad: Service stop initiated.");
    } catch { }
    }
    while (! dieNow) {
    Debug.log("Thre ad: Waiting for termination request. dieNow is " +
    dieNow + ", sleeping.");
    Thread.Sleep(50 00);
    }
    Debug.log("Thre ad: Dying.");
    }
    }

    public class TestService : System.ServiceP rocess.ServiceB ase {
    public const string serviceName = "TestServic e";
    private Thread wT = null;
    private ThreadCodeClass wT2 = null;

    public TestService() {
    ServiceName = serviceName;
    }

    static void Main() {
    System.ServiceP rocess.ServiceB ase[] ServicesToRun;
    ServicesToRun = new System.ServiceP rocess.ServiceB ase[] { new
    TestService() };
    System.ServiceP rocess.ServiceB ase.Run(Service sToRun);
    }

    protected override void OnStart(string[] args) {
    Debug.log("Serv ice: Starting service.");
    ThreadCodeClass wT2 = new ThreadCodeClass ();
    wT = new Thread(new ThreadStart(wT2 .threadMain));
    wT.Start();
    Debug.log("Serv ice: Service started.");
    }

    protected override void OnStop() {
    Debug.log("Serv ice: Stop signal received. Stopping and joining thread
    (thread state is: " + wT.ThreadState + ")");//, dieNow is " + wT2.dieNow +
    ")...");
    // Now why doesn't this work:
    wT2.dieNow = true;
    Debug.log("Serv ice: Volatile dieNow set to true. Reading dieNow yields: "
    + wT2.dieNow + ". Joining thread...");
    wT.Join();
    Debug.log("Serv ice: Service stopped.");
    }
    }
    }

    ===== End source code =====

    Copy-paste into a windows service project, compile and install as service.
    Upon starting the service, it should generate a log file, which should
    contain something like this:

    ===== Log file =====
    Service: Starting service.
    Service: Service started.
    Thread: started.
    Thread: running.
    Thread: Unexpected exception occured; I don't know how to handle this. This
    is fatal; attempting automated service shutdown. Exception was: wak wak
    simulated failure
    Service: Stop signal received. Stopping and joining thread (thread state is:
    Running)
    Thread: Service stop initiated.
    Thread: Waiting for termination request. dieNow is False, sleeping.
    ===== End log file =====

    The "Service: Stop signal received" doesn't always occur, atm. I believe
    it's a thread context switch issue, but that this isn't the real problem.
    Run the service again (kill it with "kill testservice" first) if it fails to
    produce this line :-)...
    On this system, the line is produced almost every time.

    Ciao!


Working...