Overlapped IO problem on x64

N

Nick Burkitt

Hi.

I have a C# app that uses named pipes via InteropServices. I have no
problems running on a 32-bit machine, or when targeting x86 architecture, but
it fails on a 64-bit machine when targeting x64 or AnyCPU.
The problem appears to be that ReadFile() sets lpNumberOfBytesRead to 0,
even though the receive buffer contains the data I'm expecting.
Is this a known issue, or am I just doing something dumb?
I can provide a small test app via email if needed.
Thanks,

-Nick
 
J

Jialiang Ge [MSFT]

Good morning Nick,

I appreciate it if you can send the test app to my mailbox:
(e-mail address removed), and this will give me a clearer picture of the
symptom and I will try to figure out the reason. Thanks

Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
N

Nick Burkitt

Hi Jialiang.

Thanks for your reply.
I don't seem to be able to send you email. Here's the bounce message:

<[email protected]>:
216.32.181.22 does not like recipient.
Remote host said: 554 <[email protected]>: Recipient address rejected:
Access denied
Giving up on 216.32.181.22.

-Nick
 
J

Jialiang Ge [MSFT]

My appology, Nick. I typed my mail address wrong. It should be
(e-mail address removed).

Best Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
J

Jialiang Ge [MSFT]

Hello Nick

Thank you for the sample. I spent the past four hours on this issue.
Although I have not figured out the cause of the symptom, I'd like to
update you about my current research results.

1. I debugged your sample in x64 and x86 machines and noticed that the
_OVERLAPPED struct's Internal and InternalHigh values were set differently:

x64:

KERNEL32!_OVERLAPPED
+0x000 Internal : 0x103
+0x008 InternalHigh : 0 ' always 0
+0x010 Offset : 0
+0x014 OffsetHigh : 0
+0x010 Pointer : (null)
+0x018 hEvent : 0x00000000`00000220

x86:

KERNEL32!_OVERLAPPED
+0x000 Internal : 0
+0x004 InternalHigh : 0x10 ' this is the right value.
+0x008 Offset : 0
+0x00c OffsetHigh : 0
+0x008 Pointer : (null)
+0x010 hEvent : 0x000001f8

"Internal" holds the processed I/O's error code. Both 0x103 and 0 mean that
the operation is successful (SUCCEEDED(Internal) == TRUE). However, I feel
that there must be some meaning behind 0x103. I am asking the OS team about
it and hope this can give some insights of the cause.

2. I also discussed the issue with the .NET team. They reminded me that we
added the built-in managed pipe APIs in .NET 3.5 (see System.IO.Pipes
http://msdn.microsoft.com/en-us/library/system.io.pipes.aspx), so we
recommend just using that instead of rolling our own support for pipes.
Doing low-level async I/O in managed code is very hard.

In addition, the .NET team tells me that NativeOverlapped should work just
fine on both architectures.

3. I suspected that the problem here is that we are not pinning the object
containing the NativeOverlapped. CAsyncHelper is not blittable
(http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx), and thus cannot be
pinned. I manually pinned the NativeOverlapped struct inside it and
allocate a GCHandle on the ManualResetEvent object, but it does not work
out the problem. I'm still researching in this aspect.

4. Another suggestion we'd give is to look at binding the pipe to the
ThreadPool (via ThreadPool.BindHandle) and using Overlapped instead of
using NativeOverlapped directly. This makes the pinning stuff somewhat
easier, and gives a much nicer completion model.

Best Regards,
Jialiang Ge
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
J

Jialiang Ge [MSFT]

Hello Nick

I'm reminded that System.IO.FileStream.BeginRead/Write is implemented by
using the NativeOverlapped struct, thus NativeOverlapped should work for
x64 platform. I then checked the source code of
System.IO.FileStream.BeginRead/Write, and found that it uses the
NativeOverlapped struct in this way:

// Create a managed overlapped class
// We will set the file offsets later
Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult);

// Pack the Overlapped class, and store it in the async result
NativeOverlapped* intOverlapped;
if (userCallback != null)
intOverlapped = overlapped.Pack(IOCallback, bytes);
else
intOverlapped = overlapped.UnsafePack(null, bytes);

Overlapped.Pack packs an instance of System.Threading.Overlapped into a
NativeOverlapped struct. The unmanaged pointer returned by this method can
be passed to the operating system in overlapped I/O operations. The
NativeOverlapped structure is fixed in physical memory until Unpack is
called. This is much safer than directly creating a NativeOverlapped struct
in that Overlapped.Pack manages the complex pinning logic for us.

Based on this finding, I updated your code to use Overlapped.Pack. I've
sent the new project to your mailbox. The test project has been tested in
my Windows 2003 x64 box, and it works fine. Please try it on your side and
let me know the result.

Have a very nice day!

Best Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================
 
N

Nick Burkitt

Hi Jialiang.

Thanks for the obviously considerable effort you put into finding this
solution! This appears to solve the problem completely.
Thanks again for a truly great job!

-Nick
 

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