Join 34,000+ subscribers and receive articles from our
blog about software quality, testing, QA and security.

Thread hung in Gurock.SmartInspect.Scheduler.Dequeue


#1

We are using SmartInspect to write to an encrypted text file. When the application starts to shutdown, I can see that the protocol’s Disconnect is called and the file is closed. However, the application hangs on a wait in Gurock.SmartInspect.Scheduler.Dequeue at shutdown so it cannot exit.

How can I get that thread to exit so the application can exit?


#2

Hello Doug,

please make sure to set SiAuto.Si.Enabled to false before exiting the application. This should close the thread.

Regards,
Tobias


#3

Hi,

We are trying to SmartInspect in C# Windows Form application.
I have added the following code in my singleton Logger Dispose() method and call the Dispose() method before exit:
_smartInspectLogger.Dispose();
_siSessions.Clear();
SiAuto.Si.Enabled = false;

But our applcation still hangs on
mscorlib.dll!System.Threading.Monitor.Wait(object obj) + 0x1e bytes
Gurock.SmartInspect.dll!Gurock.SmartInspect.Scheduler.Dequeue() + 0xa0 bytes
Gurock.SmartInspect.dll!Gurock.SmartInspect.Scheduler.Run() + 0x30 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x9b bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x4d bytes

The two variables _smartInspectLogger and siSessions are defined as:
private SmartInspect _smartInspectLogger;
private readonly List _siSessions = new List();

and is created in constructor of our wrapper Logger class:
_smartInspectLogger = new SmartInspect(_appName)
{
Connections = connection,
Enabled = enabled,
DefaultLevel = defLevel,
Level = defLevel
};

The Guruck.SmartInspect.dll we are using is of version 3.2.1.8782

Can you please tell me what we should do?

Thanks,

Jay


#4

I have just tried newer version of Gurock.SmartInspect.dll of 3.3.0.10181. But I am still getting the same issue on .Net 3.5 Windows 7 environment.


#5

Hello Jay,

could you share a bit more code on how and when you call Dispose for your Logger class? If you have a minimal code example or Visual Studio project on how to reproduce this behavior, this would be ideal (you can send it via email to tg@gurock.com). Also, which connection string do you use? Are you also using the SiAuto.Si instance in addition to _smartInspectLogger?

Thanks,
Tobias


#6

Helllo,

I am having the same problem as Jay of my application hanging on the Gurock.SmartInspect.Scheduler.Dequeue() method on exit when I use the following TCP connection string:

connections = tcp(host=“localhost”, reconnect=true, reconnect.interval=10s, async.enabled=true, async.clearondisconnect=true)

I wanted to use the async.enabled=true as that is recommended for TCP logging.

I have wrapped the SmartInspect logger into my own logging class and I am calling SiAuto.Si.Enabled=true whenever I create an instance of the class. Because I have several instances of this class all over my code, I can’t set SiAuto.Si.Enabled=false in a destructor or that turns off all logging as soon as one of my logger objects is out of scope.

Here is theSmartInspect code in my Logger constructor:

public PNTraceSource(String SourceName, IDictionary loggerConfigSettings, EventLog eventLog)
        {
            this.m_eventLog = eventLog;

            if (String.IsNullOrEmpty(SourceName) || String.IsNullOrWhiteSpace(SourceName)) { throw new ArgumentNullException(PNTraceStrings.TRC_TraceSourceNameNull); }

            try
            {
                // Attempt to create the SmartInspect log object
                if (m_si == null)
                {
                    // Get settings from dictionary
                    String si_configFile = (String)loggerConfigSettings["LoggerConfigFile"];

                    //SiAuto.Si.Enabled = true;
                    

                    // Create a new SmartInspect object and load the data in the specified configuration file.
                    //m_si = new SmartInspect(SourceName);
                    m_si = SiAuto.Si;
                    m_si.LoadConfiguration(si_configFile);
                }

                // Create a new logging session in the SmartInspect object with the provided source name.
                //m_trace = new Session(m_si, SourceName);
                m_trace = m_si.AddSession(SourceName);

            }
            catch (Exception ex)
            {
                // Dump the exception information to the log.
                if (m_eventLog != null)
                {
                    m_eventLog.WriteEntry( String.Format("Unable to create custom log for source {0} due to the following exception: {1}", SourceName, ex.ToString()));
                }
            }
        }

What do I need to do to get the async working with TCP? I am running the latest version of SmartInspect.

Thanks!

Sheri


#7

Hello,

Just a followup, the Si.Auto.Enabled=true was commented out in the code sample I provided but I have to set in the si_config file as well.

Also, I see this behavior in my Windows 7 development environment, as well as my Windows 2008 Server R2 testing environment.


#8

Hello Sheri,

Explicitly setting Enabled = false (or calling Dispose) is required for each SmartInspect instance that uses asynchronous protocols/logging. Otherwise, the application cannot exit properly because of active threads that are used for implementing the asynchronous logging.

Is there a reason why you are using multiple SmartInspect instances in your application instead of just SiAuto.Si? The usual workflow would be to initialize the SiAuto.Si object at application startup and then calling SiAuto.Si.Dispose during shutdown. If you are using multiple SmartInspect instances, you would need to make sure that Dispose is called for each created object.

Kind regards,
Tobias


#9

Tobias,

Thanks for the quick response.

Each instance of my logger class uses SiAuto.Si as a private static member variable (set the first time a instance of the class is created and shared across all instances) to add a new named Session. This session is what we use to coorelate all of our workflows and threads.

Sheri.


#10

Ok, thanks for the clarification. What kind of application do you have (WinForms, Windows Service etc.)? As mentioned in my previous comment, the best way to initialize and clean up SiAuto.Si would be during application startup and shutdown. If possible, I would decouple the actual configuration of SiAuto.Si from PNTraceSource and only call AddSession in this class/method (and call LoadConfiguration elsewhere, ideally on application startup). This way you can call SiAuto.Si.Dispose and clean up SmartInspect independently of your logging class.

I hope this helps. Just let me know in case anything is unclear.

Kind regards,
Tobias


#11

Tobias,

We are running a multithreaded C# console application.

The PNTraceSource is in it’s own dll (assembly), is based on an interface and is loaded dynamically on application startup.

All of the logging is encapsulated in that dll; we wanted to separte the logging component from the actual application for easy plug&play for switching logging technolgies. The only component that uses SmartInspect is the logging assembly. The application knows nothing about it and does not even reference it.

I may have to add a Shutdown method to the tracing interface, or derive from IDisposable to catch when I can call Si.Auto.Dispose. I tried keeping an internal (interlocked) counter yesterday of the number of attached sessions, and using the destructor to test the counter, calling Si.Auto.Dispose when all session are removed but I still am not sure this was the correct thing to try.

Sheri.


#12

Hello Sheri,

Thanks for the additional information. Adding a shutdown function to the interface or using IDisposable sounds like a good idea (and maybe even an additional Initialize function to configure the logging). I would advise against a (implicit) destructor/finalizer because finalizers are non-deterministic in .NET and shouldn’t reference other .NET objects according to the MS guidelines if I recall correctly. If the explicit shutdown function/IDisposable is not an option, you could also switch to the named pipe protocol and synchronous logging. Named pipes are the recommended protocol for local live logging and are much faster than TCP/IP. They also don’t have the disadvantage of blocking the application if there are problems with the connection (which is one of the main reasons for using asynchronous logging in the first place).

Regards,
Tobias