Re: Asynchronus serial port

2009-09-10 Thread Alexander Varnin
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

2009-09-09 Thread 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,
-- 
Wolfgang Walter
Studentenwerk München
Anstalt des öffentlichen Rechts
Leiter EDV
Leopoldstraße 15
80802 München




Re: Asynchronus serial port

2009-09-04 Thread Fenixk19
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

2009-09-02 Thread 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.
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

2009-09-02 Thread Fenixk19
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;
}