views:

258

answers:

1

Hello *,

I am currently investigating how Thread.Interrupt plays together with P/Invoke or native calls. I have read in MSDN that it is not possible to abort (Thread.Abort) a thread which is in the native call (other use cases might apply as well). But I did not find any reference which states the same for native threads which are in WaitSleepJoin state.

This question is not about whether one should call Abort or Interrupt, but about where I can find authorative doc on this. G-ing for this did not provide any useful output.

My test example:

#ifdef NATIVEFUNCTIONS_EXPORTS
#define NATIVEFUNCTIONS_API __declspec(dllexport)
#else
#define NATIVEFUNCTIONS_API __declspec(dllimport)
#endif

#include <iostream>

extern "C"
{
  NATIVEFUNCTIONS_API void EndlessWait(char const* mutexName)
  {
    std::cout << "entering the endless wait." << std::endl;

    HANDLE mutex = CreateMutex(NULL, FALSE, mutexName);
    WaitForSingleObject(mutex, INFINITE);

    std::cout << "leaving the endless wait." << std::endl;
  }

};

Native C++-DLL which exports a function, that endlessly waits on a mutex.

Now the C# .NET counterpart, which tries to cancel the wait:

using System;
using System.Threading;
using System.Runtime.InteropServices;

namespace InterruptingNativeWaitingThread
{
  class Program
  {
    [DllImport("NativeFunctions.dll", CharSet=CharSet.Ansi)]
    static extern void EndlessWait(string str);

    static void Main(string[] args)
    {
      string mutexName = "interprocess_mutex";
      Mutex m = new Mutex(false, mutexName);
      m.WaitOne();
      Thread t = new Thread(() => { EndlessWait(mutexName); });
      t.Start();
      Thread.Sleep(1000);

      t.Abort();
      if(!t.Join(5000))
        Console.WriteLine("Unable to terminate native thread.");

      t.Interrupt();
      if(!t.Join(5000))
        Console.WriteLine("Unable to interrupt the native wait.");

      Console.WriteLine("Release the mutex.");
      m.ReleaseMutex();
      t.Join();
    }
  }
}

Executing this app produces the following output:

entering the endless wait.
Unable to terminate native thread.
Unable to interrupt the native wait.
Release the mutex.
leaving the endless wait.

Abort does not work in this context as expected, but msdn does not say a word about interrupt. I would expect it work on one hand: since the managed thread being in Wait state also calls the native WaitForSingleObject or WaitForMultipleObjects; on the other hand, there is a possibility that native thread to be interrupted does not support expect exceptions all, what than?

Any doc is very welcome!

Many thanks,
Ovanes

P.S. I also found in MSDN that abort waits until the thread to be aborted returns from the unmanaged code and first call interrupt if the thread is in WaitSleepJoin state and than aborts it. But that does not mean that interrupt can't interrupt native WaitSleepJoin.

+1  A: 

I doubt that the thread is in the WaitSleepJoin state; Interrupt is documented to only interrupt threads in this state. Look at the ThreadState property of the thread to verify what state it is in.

Martin v. Löwis
Indeed, the thread is in Running state. Seems like .NET has own thread state management. After the line with the call to t.Abort() the thread is in AbortRequested state, but Thread.Interrupt does not interrupt it, due it was never in the WaitSleepJoin state. Many thanks!
ovanes