Good morning (%$TZ) everyone, Right. The attached sertest.c is a very simple program that attempts to open the serial port, does a select () call waiting for a byte to read with a 250ms timeout, and closes it.
It works fine with the released version 1.5.5-1 of the .dll, but it locks up when run with the 20040103 snapshot of the .dll. In fact, I've just quickly retested it with the cygwin1-20031218.dll and that also locks up. So the bug was introduced between Sep19 and Dec18 last year. Looking through the changelog for the relevant period, there are some select-related changes by cgf and some serial-related changes from Brian Ford. I would be trying to debug my way through the source at the moment, but when I checked out the latest from the CVS, I ended up with a completely non-functioning .dll (100% fails on 'make check', any attempt to launch a cygwin process crashes on startup).... So I'm kinda stuck there. I'll maybe try again after the weekend, but right now I got to get on with some work, so I hope this is a useful bug report. cheers, DaveK ------------ Details attached: (sorry for the .bz2 format, but two sets of cygcheck output already take me to 60kb, and the list mailer refuses anything over 100k) * release-dll.log and snapshot-dll.log: Traces from sysinternals' PORTMON utility. These show that the behaviour of the two dll versions is identical through setup and initialisation of the com port up to the point when an IOCTL_SERIAL_WAIT_ON_MASK is sent; for some reason, the call succeeds quickly with the release dll, but with the snapshot version, the call blocks seemingly indefinitely, and remains so until you manually kill the sertest.exe process, at which point it gets cancelled. * release-dll.txt and snapshot-dll.txt: Output generated by running the same build of the testcase under each .dll, and cygcheck -s output to confirm the dll versions used in each testrun. * strace-release-dll.out and strace-snapshot-dll.out: strace output from each of the test runs. I notice two things about these: 1) the last output from the snapshot version of the dll says "select_stuff::cleanup: calling cleanup routines", which suggests that it's one of those that has hung. 2) the release version of the dll appears to be repeatedly peeking the serial port, there are *loads* of lines that say "[select_serial] sertest 1896 peek_serial: fh->overlapped_armed 1", whereas with the snapshot version of the dll there's only one line saying peek_serial, and it has the value 0 for overlapped_armed. ------------
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <pthread.h> #include <termios.h> #include <unistd.h> #include <sys/time.h> #include <sys/select.h> /** Reads the serial port, implementing a timeout. * * @param serialfd Fd returned earlier from serial_init (...) * @param buffer The destination address for received bytes. * @param buflen The maximum amount of space available in the buffer. * @param timeout_ms Timeout in milliseconds; zero to poll, -ve for infinite. * * @return -1 if error, 0 if timeout before any data rx'd, else num * bytes placed into buffer (up to max of buflen). * * @todo Perhaps implement win32 style serial handling */ int serial_read_with_timeout (int serialfd, void *buffer, int buflen, int timeout_ms) { struct timeval tmo, *tmoptr; int rv; fd_set readfds; //fd_set dummy1, dummy2; //FD_ZERO (&dummy1); FD_ZERO (&dummy2); FD_ZERO (&readfds); FD_SET (serialfd, &readfds); tmo.tv_sec = timeout_ms / 1000; tmo.tv_usec = (timeout_ms - (1000 * tmo.tv_sec)) * 1000; tmoptr = (timeout_ms < 0) ? NULL : &tmo; printf ("b4sel %d, %p, 0, 0, %p { %ld, %ld }\n", 1+serialfd, &readfds, tmoptr, tmo.tv_sec, tmo.tv_usec); rv = select (1 + serialfd, &readfds, NULL, NULL, tmoptr); //rv = select (1 + serialfd, &readfds, &dummy1, &dummy2, tmoptr); printf ("afsel\n"); // So what happened? rv is 0 => no fd set, -1 = error, else there must be readable data if (rv <= 0) return rv; // huzzah! there is some data to actually read.... // we could always do int bytes; ioctl(fd, FIONREAD, &bytes); // at this point, but nonblocking means we should be ok anyway....... rv = read (serialfd, buffer, buflen); return rv; } int main (int argc, const char **argv) { int rv, fd; char buff[8]; struct termios tio; fd = open ("/dev/com1", O_RDWR | O_BINARY | O_NONBLOCK | O_NOCTTY | O_NDELAY ); if (fd < 0) { fprintf (stderr, "oops error opening com1 %d\n", errno); return -1; } // Dunno for sure if this just duplicates setting O_NONBLOCK fcntl(fd, F_SETFL, FNDELAY); // Set the serial port to the baud rate chosen and 8n1. rv = tcgetattr (fd, &tio); if (rv) { fprintf (stderr, "Can't get options - error %d\n", errno); close (fd); return -1; } // Not implemented.... cfmakeraw (&tio); ... equivalent is.... tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|INPCK|IUCLC); tio.c_oflag &= ~OPOST; tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN|ECHOE); tio.c_cflag &= ~(CSIZE|PARENB); tio.c_cflag |= CS8 | CLOCAL | CREAD; // Now modify the defaults with chosen settings. rv = cfsetospeed (&tio, B57600); if (!rv) rv = cfsetispeed (&tio, B57600); if (rv) fprintf (stderr, "ERROR: Baud rate not recognized\n"); tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8; tio.c_cflag = (tio.c_cflag & ~PARENB); tio.c_cflag = (tio.c_cflag & ~CSTOPB); // and implement those settings. rv = tcsetattr (fd, TCSANOW, &tio); if (rv) { fprintf (stderr, "Error %d setting options\n", errno); close (fd); return -1; } // so try reading it rv = serial_read_with_timeout (fd, buff, 1, 250); fprintf (stderr, "serial read: rv %d char $%02x\n", rv, (unsigned int)buff[0]); // we done now. rv = close (fd); fprintf (stderr, "close gives %d\n", fd); return 0; }
makefile
Description: Binary data
release-dll.txt.bz2
Description: Binary data
snapshot-dll.txt.bz2
Description: Binary data
strace-snapshot-dll.out.bz2
Description: Binary data
strace-release-dll.out.bz2
Description: Binary data
release-dll.LOG
Description: Binary data
snapshot-dll.LOG
Description: Binary data
-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/