Marshal.GetLastWin32Error not Thread Safe?

G

Guest

the Hi

the method GetLastWin32Error should be a wrapper to win32's GetLastError.

"Retrieves the calling thread's last-error code value. The last-error code
is maintained on a per-thread basis. Multiple threads do not overwrite each
other's last-error code" (from MSDN)

But from time to time, when I use GetLastWin32Error, I got a returned value
which tell's an Error occured - also it happened on another .Net's Thread.

I looked on MSDN article about "GetLastWin32Error" I couldn't find that this
method is Thread Safe.

How can I be sure that I get an error from my thread, and not from another
one?

See following code for examle:
(it is not always find the exceptions - stop and restart multiple times)

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool SetVolumeLabel(string lpRootPathName, string
lpVolumeName);


static void Main(string[] args)
{
System.Threading.ThreadStart threadStartErrors = new
System.Threading.ThreadStart(ThrowingErrors);
System.Threading.Thread threadErrors = new
System.Threading.Thread(threadStartErrors);

System.Threading.ThreadStart threadStartGetErrors = new
System.Threading.ThreadStart(GetErrors);
System.Threading.Thread threadGetErrors = new
System.Threading.Thread(threadStartGetErrors);

threadErrors.Start();
threadGetErrors.Start();

}

static void ThrowingErrors()
{
while (true)
{
SetVolumeLabel("XYZ:\\", "My Imaginary Drive ");
System.Threading.Thread.Sleep(100);
}
}

static void GetErrors()
{
while (true)
{
if (Marshal.GetLastWin32Error() != 0)
{
try
{

Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}

System.Threading.Thread.Sleep(150);
}
}
 
M

Mattias Sjögren

But from time to time, when I use GetLastWin32Error, I got a returned value
which tell's an Error occured - also it happened on another .Net's Thread.

I'v tried running your code a number of times now on all different
versions of the CLR. So far I haven't been able to reproduce the
behavior you describe.


Mattias
 
G

Guest

Thanks for trying.

My configuration:

Windows 2003 Server with SP 2
..Net 2.0
The project was simple Console Application which was created by the VS 2005
wizard.

I succeed reapet this more than one time.

this is actually a test for a real problem we have in our application where
during Load Test we get an "Invalid Handle exception" during
SqlConnection.Open()
I looked at the call stack and used reflector to see the code - and this
GetLastWin32Error is the reason for the exception (and I know that our app
throw a lot of win32 invalid handle exceptions during load test)

I suspect that "Marshal.GetLastWin32Error" assume to have the same physical
thread all the time, while, as far as I know, in .Net 2.0 this is not true
any more.
(the 1 to 1 relation between .Net Logical thread and System physical thread
wasn't promised even on 1.1, but actually not true any more in 2.0 - as far
as I know)

Can someone approve or decline what I'm saying?
 
M

Mattias Sjögren

I suspect that "Marshal.GetLastWin32Error" assume to have the same physical
thread all the time, while, as far as I know, in .Net 2.0 this is not true
any more.
(the 1 to 1 relation between .Net Logical thread and System physical thread
wasn't promised even on 1.1, but actually not true any more in 2.0 - as far
as I know)

Can someone approve or decline what I'm saying?

It's still true in 2.0 (but I'm not saying you should rely on it
always beeing that way).



Mattias
 
P

Peter Duniho

[...]
But from time to time, when I use GetLastWin32Error, I got a returned
value
which tell's an Error occured - also it happened on another .Net's
Thread.

I can't say that I really know the answer to the question. However, I
will point out that you cannot just call GetLastError() or any of its
variations any time you like. The value is only valid if you have just
called a function that can set it *and* that has set it (in which case
that function would return a general purpose error code, indicating that
you should call GetLastError() or some variant thereof).

In other words, your loop that just keeps calling GetLastWin32Error() over
and over is not something I'd expect to work reliably.

I can't speak to the general reliability of the method, but I can tell you
that if you are calling GetLastWin32Error() in situations in which you did
not just return from a Windows function that is known to set it, and which
has specifically returned a value indicating that it *has* set it, then
that's a bug in your code.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top