I have an application running on Windows Server 2003, that, according
to PortMon monitoring software, is using calls to IRP_MJ_READ to read
data from a serial port. Normally, to read a 37 byte message (for
example), there will be a series of 4 calls to IRP_MJ_READ that result
in 8 bytes of data from each read, then a final call that reads the
final 5 bytes. Everything works fine. Occasonally, during the series
of reads (let's say the 3rd read for example), the call to IRP_MJ_READ
will result in 16 bytes of data (32 bytes read total so far), and no
more calls to IRP_MJ_READ. The final 5 bytes of data are forever lost
(a protocol analyzer trace shows that the entire 37 bytes entered the
DB9 connector on the back of tyhe server). The application that was
waiting for the data continues to issue calls to
IOCTL_SERIAL_GET_COMMSTATUS, IOCTL_SERIAL_GET_MODEMSTATUS, and
IOCTL_SERIAL_WAIT_ON_MASK, but the remaing 5 bytes never show up, so
it times out while waiting for an ETX character that is at the end of
the missing bytes. Any ideas on what could be causing this?

I am not a developer, but am stuck in the middle of a lot of finger
pointing between the server manufacturer (with their hardened drivers)
and the application developer that is using the serial data. Any help
you could give me that would give me some "ammo" so I can lean on the
appropriate vendor would be helpful.

Thank you.

Re: IRP_MJ_READ problem by chris

chris
Wed Feb 06 14:52:53 CST 2008

Lauren,

There isn't enough information here to totally determine "fault" for
sure on either side, but I can say for sure that if the application
were coded more defensively, this failure that you're describing could
have been avoided.

It sounds like what's going on is the application is expecting
(exactly) eight bytes at a time from its read requests, but is issuing
reads that are actually larger than that (at least 16 bytes, based on
your description of the failure case in "step 3" below), which allows
it to lose state in the data stream.

Ultimately, based on the rate at which the serial driver is receiving
(and buffering) data, and also the rate at which the application is
requesting data, it seems like there is an occasional case where two
"reports" (of eight bytes each) are available in the buffer, and the
application reads it all in, but is only expecting one "report" and so
it chokes.

Now, why is this happening? Well, a few possibilities:

1) Less likely -- the serial driver that was provided to you doesn't
strictly implement the MS-provided serial timeout semantics, and the
application is expecting it to do so (which is risky), and thus it
occasionally chokes when there is a deviation.

2) More likely -- some combination of timing (on the device) and
scheduling (on the PC) causes two "reports" to be buffered up, and the
application doesn't know to handle it when it consumes both.

When trying to "continuously read" from a serial port, I find that's
easiest just to set up the read loop using code like the below, and
then just using a state machine to keep track of where I am as I read
the data, rather than relying on the size of my read request to
properly delineate the data for me. That way, data is never
"missed" (and provides for easier logging also).

----

void process_data(unsigned char *buf, DWORD dwLen);

unsigned char buf[4096];
DWORD dwBytesRead;
COMMTIMEOUTS c;
ZeroMemory(&c, sizeof(COMMTIMEOUTS));

c.ReadIntervalTimeout = -1;
c.ReadMultiplierTimeout = -1;
c.ReadConstantTimeout = 500;

while (ReadFile(h, buf, 4096, &dwBytesRead, NULL))
{
process_data(buf, dwBytesRead);
}

-Chris

On Feb 6, 9:56 am, Lauren <lmill...@arrowheadcu.org> wrote:

> I have an application running on Windows Server 2003, that, according
> to PortMon monitoring software, is using calls to IRP_MJ_READ to read
> data from a serial port. Normally, to read a 37 byte message (for
> example), there will be a series of 4 calls to IRP_MJ_READ that result
> in 8 bytes of data from each read, then a final call that reads the
> final 5 bytes. Everything works fine. Occasonally, during the series
> of reads (let's say the 3rd read for example), the call to IRP_MJ_READ
> will result in 16 bytes of data (32 bytes read total so far), and no
> more calls to IRP_MJ_READ. The final 5 bytes of data are forever lost
> (a protocol analyzer trace shows that the entire 37 bytes entered the
> DB9 connector on the back of tyhe server). The application that was
> waiting for the data continues to issue calls to
> IOCTL_SERIAL_GET_COMMSTATUS, IOCTL_SERIAL_GET_MODEMSTATUS, and
> IOCTL_SERIAL_WAIT_ON_MASK, but the remaing 5 bytes never show up, so
> it times out while waiting for an ETX character that is at the end of
> the missing bytes. Any ideas on what could be causing this?
>
> I am not a developer, but am stuck in the middle of a lot of finger
> pointing between the server manufacturer (with their hardened drivers)
> and the application developer that is using the serial data. Any help
> you could give me that would give me some "ammo" so I can lean on the
> appropriate vendor would be helpful.