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