Re: Asynchronus serial port
Thanks, I'll check it, when i have time. Wolfgang Walter пишет: > Am Donnerstag, 3. September 2009 schrieb Mike Kaplinskiy: > >> On Wed, Sep 2, 2009 at 7:31 PM, Fenixk19 wrote: >> >>> Hello! I've already post the >>> bug(http://bugs.winehq.org/show_bug.cgi?id=19713) on this subject, but i >>> need more help. So I've decided to write here. >>> There is a problem in wine. When I use asynchronous serial port read, >>> data never comes. Event, caused by select comes. But operation status >>> stays pending, and i can't do anything to this serial port anymore. In >>> windows it never get pending, and port can be accessed just after data >>> arrival. Seems to be wineserver problem, but i don't know, where to look >>> at. What code respond for asynchronous serial port in wineserver? >>> Alexander. >>> P.S. Test program attached. >>> >> Hi, >> >> Alexandre would be the guy to talk to about wineserver-related things. >> Sadly he's off on a long weekend. Does the attached patch help solve >> the problem? >> > > Isn't setting commio->iosb->u.Status racy? > > commio->iosb may be set from wait_for_event() which is called by an extra > thread or by io_control(). > > Couldn't it happen that > > wait_on starts the thread > wait_for_event sets the commio->iosb->u.Status to STATUS_SUCCESS > wait_on returns to io_control STATUS_PENDING > io_control overwrites commio->iosb->u.Status with STATUS_PENDING > > I think io_control() should set commio->iosb->u.Status to STATUS_PENDING > before calling wait_on(). After wait_on() io_control() should not set > commio->iosb->u.Status if wait_on() returns STATUS_PENDING. Here the idea: > > -- > case IOCTL_SERIAL_WAIT_ON_MASK: > if (lpOutBuffer && nOutBufferSize == sizeof(DWORD)) > { > piosb->u.Status = STATUS_PENDING; > piosb->Information = sz; > if (!(status = wait_on(hDevice, fd, hEvent, piosb, lpOutBuffer))) > sz = sizeof(DWORD); > else if (status == STATUS_PENDING) > return status; > } > else > status = STATUS_INVALID_PARAMETER; > break; > --- > > > Regards, >
Re: Asynchronus serial port
Am Donnerstag, 3. September 2009 schrieb Mike Kaplinskiy: > On Wed, Sep 2, 2009 at 7:31 PM, Fenixk19 wrote: > > Hello! I've already post the > > bug(http://bugs.winehq.org/show_bug.cgi?id=19713) on this subject, but i > > need more help. So I've decided to write here. > > There is a problem in wine. When I use asynchronous serial port read, > > data never comes. Event, caused by select comes. But operation status > > stays pending, and i can't do anything to this serial port anymore. In > > windows it never get pending, and port can be accessed just after data > > arrival. Seems to be wineserver problem, but i don't know, where to look > > at. What code respond for asynchronous serial port in wineserver? > > Alexander. > > P.S. Test program attached. > > Hi, > > Alexandre would be the guy to talk to about wineserver-related things. > Sadly he's off on a long weekend. Does the attached patch help solve > the problem? Isn't setting commio->iosb->u.Status racy? commio->iosb may be set from wait_for_event() which is called by an extra thread or by io_control(). Couldn't it happen that wait_on starts the thread wait_for_event sets the commio->iosb->u.Status to STATUS_SUCCESS wait_on returns to io_control STATUS_PENDING io_control overwrites commio->iosb->u.Status with STATUS_PENDING I think io_control() should set commio->iosb->u.Status to STATUS_PENDING before calling wait_on(). After wait_on() io_control() should not set commio->iosb->u.Status if wait_on() returns STATUS_PENDING. Here the idea: -- case IOCTL_SERIAL_WAIT_ON_MASK: if (lpOutBuffer && nOutBufferSize == sizeof(DWORD)) { piosb->u.Status = STATUS_PENDING; piosb->Information = sz; if (!(status = wait_on(hDevice, fd, hEvent, piosb, lpOutBuffer))) sz = sizeof(DWORD); else if (status == STATUS_PENDING) return status; } else status = STATUS_INVALID_PARAMETER; break; --- Regards, -- Wolfgang Walter Studentenwerk München Anstalt des öffentlichen Rechts Leiter EDV Leopoldstraße 15 80802 München
Re: Asynchronus serial port
Yes, this patch solved problem. Great thanks. But there is another one. It hangs on another call of GetOverlappedResult, where windows going on. It hangs the same way - function always return, because ovOverlapped.Internal is STATUS_PENDING. In attached file part of new test problem, to show where it is. I'll send full variant on bugzilla in minutes. http://bugs.winehq.org/show_bug.cgi?id=19713 Mike Kaplinskiy пишет: > On Wed, Sep 2, 2009 at 7:31 PM, Fenixk19 wrote: > >> Hello! I've already post the >> bug(http://bugs.winehq.org/show_bug.cgi?id=19713) on this subject, but i >> need more help. So I've decided to write here. >> There is a problem in wine. When I use asynchronous serial port read, >> data never comes. Event, caused by select comes. But operation status >> stays pending, and i can't do anything to this serial port anymore. In >> windows it never get pending, and port can be accessed just after data >> arrival. Seems to be wineserver problem, but i don't know, where to look >> at. What code respond for asynchronous serial port in wineserver? >> Alexander. >> P.S. Test program attached. >> >> >> >> >> > > Hi, > > Alexandre would be the guy to talk to about wineserver-related things. > Sadly he's off on a long weekend. Does the attached patch help solve > the problem? > > Mike. > // <...> BOOL bWRes = WaitCommEvent(hComm, &evtMask, &ovOverlapped); printf("After WaitCommEvent 1.\n"); if (!bWRes) { if ((dwError = GetLastError()) == ERROR_IO_PENDING) {// ÐапÑÑено ожидание ÑобÑÑÐ¸Ñ COM поÑÑа //fWaitOnStat = TRUE; WHILE_LOOP: dwResult = WaitForSingleObject(ovOverlapped.hEvent, 50); printf("%d: WaitForSingleObject, retval=%d\n", i++, dwResult); switch(dwResult) { case WAIT_TIMEOUT: //ÐиÑего не пÑоизоÑло по ÑаймаÑÑÑ, ждем... Sleep(1); goto WHILE_LOOP; break; case WAIT_FAILED: printf("FATAL. WaitForSingleObject WAIT_FAILED.\n"); // WaitForSingleObject завеÑÑилаÑÑ Ð½ÐµÑдаÑно fWaitOnStat = FALSE;// ÐÑоизоÑло ÑобÑÑие COM поÑÑа break; case WAIT_OBJECT_0: if (!(bOvResult = GetOverlappedResult(hComm, &ovOverlapped, &dwOvRes, FALSE))) { printf("FATAL. GetOverlappedResult() system error.\n"); // GetOverlappedResult завеÑÑилаÑÑ Ð½ÐµÑдаÑно return 0; break; } else { // ÐнализиÑÑем ÑобÑÑие // ÐÑоизоÑло ÑобÑÑие COM поÑÑа if (evtMask & EV_RXCHAR) { memset(m_buf, 0 , ncBufferSize); printf("ReadFile start.\n"); if (!(dwReadResult = ReadFile(hComm, m_buf, ncBufferSize, &dwRead, &ovOverlapped))) {//ÐаÑинаем опеÑаÑÐ¸Ñ ÑÑÐµÐ½Ð¸Ñ Ð¸Ð· поÑÑа printf("ReadFile done.\n"); dwError = GetLastError(); if (dwError == ERROR_IO_PENDING) { printf("dwError==ERROR_IO_PENDING\n"); bOvResult = GetOverlappedResult(hComm, &ovOverlapped, &dwOvRes, FALSE); dwError = GetLastError(); if (!bOvResult) while (dwError == ERROR_IO_INCOMPLETE) {//Wine get stuck in this loop. printf("Waiting for result.\tovOverlapped.Internal=%lu\t(Here wine get stuck. But windows gets some event and going on.\n",ovOverlapped.Internal); bOvResult = GetOverlappedResult(hComm, &ovOverlapped, &dwOvRes, FALSE); dwError = GetLastError(); if (bOvResult) break; if (!bOvResult && (dwError != ERROR_IO_INCOMPLETE)) break; Sleep(50); } if (bOvResult) {/* ALL IS GREAT */} } } }//if (evtMask & EV_RXCHAR) else if (evtMask & EV_BREAK) { return 0; break; } else Sleep(1); } break; } } else {// ÐÑибка ÑÑнкÑии WaitCommEvent printf("FATAL. WaitCommEvent error (%d).\n", dwError); } } else {// WaitCommEvent веÑнÑла ÑпÑавление ÑÑÐ°Ð·Ñ printf("WaitCommEvent 2.\n"); Sleep(1); } //<...>
Re: Asynchronus serial port
On Wed, Sep 2, 2009 at 7:31 PM, Fenixk19 wrote: > Hello! I've already post the > bug(http://bugs.winehq.org/show_bug.cgi?id=19713) on this subject, but i > need more help. So I've decided to write here. > There is a problem in wine. When I use asynchronous serial port read, > data never comes. Event, caused by select comes. But operation status > stays pending, and i can't do anything to this serial port anymore. In > windows it never get pending, and port can be accessed just after data > arrival. Seems to be wineserver problem, but i don't know, where to look > at. What code respond for asynchronous serial port in wineserver? > Alexander. > P.S. Test program attached. > > > > Hi, Alexandre would be the guy to talk to about wineserver-related things. Sadly he's off on a long weekend. Does the attached patch help solve the problem? Mike. diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c index dfb00e1..2a448ed 100644 --- a/dlls/ntdll/serial.c +++ b/dlls/ntdll/serial.c @@ -851,6 +851,7 @@ typedef struct async_commio { HANDLE hDevice; DWORD* events; +IO_STATUS_BLOCK*iosb; HANDLE hEvent; DWORD evtmask; DWORD mstat; @@ -985,12 +986,14 @@ static DWORD CALLBACK wait_for_event(LPVOID arg) } if (needs_close) close( fd ); } +if (commio->iosb) +commio->iosb->u.Status = *commio->events ? STATUS_SUCCESS : STATUS_CANCELLED; if (commio->hEvent) NtSetEvent(commio->hEvent, NULL); RtlFreeHeap(GetProcessHeap(), 0, commio); return 0; } -static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, DWORD* events) +static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, PIO_STATUS_BLOCK piosb, DWORD* events) { async_commio* commio; NTSTATUSstatus; @@ -1003,6 +1006,7 @@ static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, DWORD* events) commio->hDevice = hDevice; commio->events = events; +commio->iosb= piosb; commio->hEvent = hEvent; get_wait_mask(commio->hDevice, &commio->evtmask); @@ -1301,7 +1305,7 @@ static inline NTSTATUS io_control(HANDLE hDevice, case IOCTL_SERIAL_WAIT_ON_MASK: if (lpOutBuffer && nOutBufferSize == sizeof(DWORD)) { -if (!(status = wait_on(hDevice, fd, hEvent, lpOutBuffer))) +if (!(status = wait_on(hDevice, fd, hEvent, piosb, lpOutBuffer))) sz = sizeof(DWORD); } else
Asynchronus serial port
Hello! I've already post the bug(http://bugs.winehq.org/show_bug.cgi?id=19713) on this subject, but i need more help. So I've decided to write here. There is a problem in wine. When I use asynchronous serial port read, data never comes. Event, caused by select comes. But operation status stays pending, and i can't do anything to this serial port anymore. In windows it never get pending, and port can be accessed just after data arrival. Seems to be wineserver problem, but i don't know, where to look at. What code respond for asynchronous serial port in wineserver? Alexander. P.S. Test program attached. #include #include int main() { HANDLE hSerial = CreateFile(".\\COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength=sizeof(dcbSerialParams); dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; dcbSerialParams.fBinary = 1; dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE; dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE; SetCommState(hSerial, &dcbSerialParams); COMMTIMEOUTS timeouts={0}; timeouts.ReadIntervalTimeout=250; timeouts.ReadTotalTimeoutConstant=250; timeouts.ReadTotalTimeoutMultiplier=250; timeouts.WriteTotalTimeoutMultiplier = timeouts.WriteTotalTimeoutConstant = 250; SetCommTimeouts(hSerial, &timeouts); SetupComm(hSerial, 1024, 1024); PurgeComm(hSerial, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT); SetCommMask(hSerial, EV_RXCHAR); int iters = 0; DWORD dwResult = 0; DWORD dwReadResult = 0; DWORD dwOvRes = 0; DWORD bOvResult = 0; char buffer[2048]; DWORD dwRead = 0; DWORD evtMask, dwError; DWORD dwTest; OVERLAPPED ovOverlapped; ovOverlapped.Offset = ovOverlapped.OffsetHigh = 0; ovOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); BOOL bRes = WaitCommEvent(hSerial, &evtMask, &ovOverlapped); if(!bRes) { dwError=GetLastError(); if (dwError == ERROR_IO_PENDING) { printf("dwError = ERROR_IO_PENDING\n"); printf("*** All preparations is done. Now we are gonna wait for event.\n"); dwResult = WaitForSingleObject(ovOverlapped.hEvent, INFINITE); do { bOvResult = GetOverlappedResult(hSerial, &ovOverlapped, &dwOvRes, FALSE); dwError=GetLastError(); printf("ovOverlapped.Internal = %lu\n", ovOverlapped.Internal); printf("dwError = %d\n", dwError); printf("bOvResult = %d\n", bOvResult); if (bOvResult) break; if(ovOverlapped.Internal==259) printf("*** ovOverlapped.Internal==259. That means, that event is in progress. It is a bug. Because in windows it will never reach this point. It seems that data get stuck somewhere, but event is sent. If we try to read data, we'll get nothing.\n"); Sleep(500); } while (dwError == ERROR_IO_INCOMPLETE); if (bOvResult) { printf("*** All is done good. It means, that we are in Windows, or Wine is fixed(hope so).\n"); printf("OK.\n"); if (evtMask & EV_RXCHAR) { printf("EV_RXCHAR.\n"); } } else { printf("BAD.\n"); } } } return 0; }