Bug in Win32file WaitCommEvent ???
Grant Edwards
grante at visi.com
Wed Nov 20 22:57:03 EST 2002
In article <3ddaa58d$0$4459$a1866201 at newsreader.visi.com>, Grant Edwards wrote:
> My understanding is that (in C) you:
>
> 1) Call WaitCommEvent() and give it three parameters:
> * File handle
> * a pointer to where the output mask value is to be stored
> * a pointer to an overlapped struct
>
> 2) WaitCommEvent() returns immediately.
>
> 3) Call one of the WaitXXX() functions to wait on the event in
> the overloapped struct.
>
> 4) When the event is triggered WaitXXX() returns. Check the
> value stored via the output mask pointer passed in 1)
> above.
I've verefied that the above is correct. I wrote a C program that verifies
that the value pointed to by the pointer passed to WaitCommEvent() is
written to later: after the event happens.
That means that the Win32all WaitCommEvent() wrapper is passing a pointer to
a local, automatic variable that used in a write operation sometime after
the end of the referenced variable's lifetime. Why this hasn't caused
problems, I don't know. Good karma, I guess.
I don't know if the write happens immediately when the event occurs or if it
is delayed until WaitForXXX() is called [I called WaitForXXX() immediately].
Either way, it happens long after WaitCommEvent() has returned. That's the
way it's described on the MSDN web page, and surprisingly, that's the way it
works.
BTW, the demo code on MSDN showing WaitCommEvent() being used to wait for
CTS or DSR events does _not_ work. I compiled it and ran it. The call to
WaitCommEvent() always returned immediately with a mask of 0. It doesn't
wait for anything...
The source and executable for the test program are available at:
ftp://ftp.visi.com/users/grante/python/hello.c
ftp://ftp.visi.com/users/grante/python/hello.exe
The test program opens COM1, and waits for an RX_CHAR event.
The WaitCommEvent() call returns immediately after setting the mask output
value to 0.
The subsequent WaitForSingleObject() call waits until I send a byte to COM1
(in the example run below is about 2 seconds later), then returns after
setting the mask output value to 1:
Here's the output:
dwEvtMask=5555aaaa
hello.c:42 0.306s Calling WaitCommEvent
hello.c:46 0.306s WaitCommEvent returned
rc=0 dwEvtMask=00000000
hello.c:48 0.306s Calling WaitForSingleEvent
hello.c:52 2.481s WaitForSingleEvent returned
rc=0 dwEvtMask=00000001
hello.c:54 2.481s done
[the floating point value is time since program start]
And here's the program:
--------------------------------8<--------------------------------
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>
#define Trace(s) printf("%s:%d %0.3fs %s\n", \
__FILE__,__LINE__, \
((double)clock())/CLOCKS_PER_SEC,\
s)
int main(void)
{
DCB dcb;
HANDLE hCom;
OVERLAPPED o;
BOOL fSuccess,rc;
DWORD dwEvtMask = 0x5555AAAA;
hCom = CreateFile( "COM1",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attributes
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
); assert(hCom != INVALID_HANDLE_VALUE);
rc = GetCommState(hCom,&dcb); assert(rc);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
rc = SetCommState(hCom,&dcb); assert(rc);
rc = SetCommMask(hCom, EV_RXCHAR); assert(rc);
o.hEvent = CreateEvent(
NULL, // no security attributes
FALSE, // auto reset event
FALSE, // not signaled
NULL // no name
);
assert(o.hEvent);
printf("dwEvtMask=%08x\n",dwEvtMask);
Trace("Calling WaitCommEvent");
rc = WaitCommEvent(hCom, &dwEvtMask, &o);
Trace("WaitCommEvent returned");
printf("rc=%d dwEvtMask=%08x\n",rc,dwEvtMask);
Trace("Calling WaitForSingleEvent");
rc = WaitForSingleObject(o.hEvent,50000);
Trace("WaitForSingleEvent returned");
printf("rc=%d dwEvtMask=%08x\n",rc,dwEvtMask);
Trace("done");
return 0;
}
--------------------------------8<--------------------------------
More information about the Python-list
mailing list