2016-04-05 21:24 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* src/rtl/gttone.c
    ! use asm {} directive only in CLANG BCC builds - asm {} needs TASM
      so using it breaks Harbour compilation with free BorlandC command
      line tools which do not contain TASM.

  * src/rtl/hbsocket.c
  * src/rtl/hbproces.c
  * src/rtl/filesys.c
  * src/rtl/hbcom.c
    ! use poll() instead of select() in POSIX.1-2001 compliant *nix builds
      It fixes the problem with file handles >= 1024
      Please make tests in different *nix builds. It affects sockets, pipes
      and serial ports.
This commit is contained in:
Przemysław Czerpak
2016-04-05 21:24:05 +02:00
parent 037ccea634
commit 5a2af0b426
6 changed files with 634 additions and 123 deletions

View File

@@ -10,6 +10,21 @@
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
*/
2016-04-05 21:24 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* src/rtl/gttone.c
! use asm {} directive only in CLANG BCC builds - asm {} needs TASM
so using it breaks Harbour compilation with free BorlandC command
line tools which do not contain TASM.
* src/rtl/hbsocket.c
* src/rtl/hbproces.c
* src/rtl/filesys.c
* src/rtl/hbcom.c
! use poll() instead of select() in POSIX.1-2001 compliant *nix builds
It fixes the problem with file handles >= 1024
Please make tests in different *nix builds. It affects sockets, pipes
and serial ports.
2016-04-05 16:27 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* contrib/hbnetio/netiosrv.c
* minor optimization

View File

@@ -111,6 +111,12 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#if defined( _POSIX_C_SOURCE ) && _POSIX_C_SOURCE >= 200112L
/* use poll() instead of select() to avoid FD_SETSIZE (1024 in Linux)
file handle limit */
#define HB_HAS_POLL
#include <poll.h>
#endif
#endif
#if ! defined( HB_OS_WIN )
# include <errno.h>
@@ -1136,15 +1142,51 @@ HB_SIZE hb_fsPipeIsData( HB_FHANDLE hPipeHandle, HB_SIZE nBufferSize,
}
#elif defined( HB_OS_UNIX ) && ! defined( HB_OS_SYMBIAN )
{
int iResult;
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = nTimeOut <= 0 ? 0 : hb_dateMilliSeconds();
struct pollfd fds;
fds.fd = hPipeHandle;
fds.events = POLLIN;
fds.revents = 0;
for( ;; )
{
int tout = nTimeOut < 0 || nTimeOut > 1000 ? 1000 : ( int ) nTimeOut;
iResult = poll( &fds, 1, tout );
hb_fsSetIOError( iResult >= 0, 0 );
if( iResult > 0 && ( fds.revents & POLLIN ) == 0 )
iResult = 0;
if( ( ( iResult == 0 && ( nTimeOut < 0 || nTimeOut > 1000 ) ) ||
( iResult == -1 && nTimeOut != 0 && hb_fsOsError() == ( HB_ERRCODE ) EINTR ) ) &&
hb_vmRequestQuery() == 0 )
{
if( nTimeOut < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
nTimeOut -= timecurr - timer;
if( nTimeOut > 0 )
continue;
}
}
}
break;
}
#else
struct timeval tv;
fd_set rfds;
int iResult;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
HB_MAXUINT timer = nTimeOut <= 0 ? 0 : hb_dateMilliSeconds();
#else
# else
tv.tv_sec = ( long ) nTimeOut / 1000;
tv.tv_usec = ( long ) ( nTimeOut % 1000 ) * 1000;
#endif
# endif
for( ;; )
{
@@ -1153,13 +1195,13 @@ HB_SIZE hb_fsPipeIsData( HB_FHANDLE hPipeHandle, HB_SIZE nBufferSize,
tv.tv_sec = 1;
tv.tv_usec = 0;
}
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else
{
tv.tv_sec = ( long ) nTimeOut / 1000;
tv.tv_usec = ( long ) ( nTimeOut % 1000 ) * 1000;
}
#endif
# endif
FD_ZERO( &rfds );
FD_SET( hPipeHandle, &rfds );
@@ -1171,7 +1213,7 @@ HB_SIZE hb_fsPipeIsData( HB_FHANDLE hPipeHandle, HB_SIZE nBufferSize,
hb_fsOsError() != ( HB_ERRCODE ) EINTR ||
hb_vmRequestQuery() != 0 )
break;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else if( nTimeOut > 0 )
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
@@ -1182,8 +1224,10 @@ HB_SIZE hb_fsPipeIsData( HB_FHANDLE hPipeHandle, HB_SIZE nBufferSize,
timer = timecurr;
}
}
#endif
# endif
}
#endif /* HB_HAS_POLL */
if( iResult > 0 )
nToRead = nBufferSize;
}
@@ -1334,15 +1378,51 @@ HB_SIZE hb_fsPipeWrite( HB_FHANDLE hPipeHandle, const void * buffer, HB_SIZE nSi
}
#elif defined( HB_OS_UNIX ) && ! defined( HB_OS_SYMBIAN )
{
int iResult;
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = nTimeOut <= 0 ? 0 : hb_dateMilliSeconds();
struct pollfd fds;
fds.fd = hPipeHandle;
fds.events = POLLOUT;
fds.revents = 0;
for( ;; )
{
int tout = nTimeOut < 0 || nTimeOut > 1000 ? 1000 : ( int ) nTimeOut;
iResult = poll( &fds, 1, tout );
hb_fsSetIOError( iResult >= 0, 0 );
if( iResult > 0 && ( fds.revents & POLLOUT ) == 0 )
iResult = 0;
if( ( ( iResult == 0 && ( nTimeOut < 0 || nTimeOut > 1000 ) ) ||
( iResult == -1 && nTimeOut != 0 && hb_fsOsError() == ( HB_ERRCODE ) EINTR ) ) &&
hb_vmRequestQuery() == 0 )
{
if( nTimeOut < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
nTimeOut -= timecurr - timer;
if( nTimeOut > 0 )
continue;
}
}
}
break;
}
#else
struct timeval tv;
fd_set wfds;
int iResult;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
HB_MAXUINT timer = nTimeOut <= 0 ? 0 : hb_dateMilliSeconds();
#else
# else
tv.tv_sec = ( long ) nTimeOut / 1000;
tv.tv_usec = ( long ) ( nTimeOut % 1000 ) * 1000;
#endif
# endif
for( ;; )
{
@@ -1351,13 +1431,13 @@ HB_SIZE hb_fsPipeWrite( HB_FHANDLE hPipeHandle, const void * buffer, HB_SIZE nSi
tv.tv_sec = 1;
tv.tv_usec = 0;
}
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else
{
tv.tv_sec = ( long ) nTimeOut / 1000;
tv.tv_usec = ( long ) ( nTimeOut % 1000 ) * 1000;
}
#endif
# endif
FD_ZERO( &wfds );
FD_SET( hPipeHandle, &wfds );
@@ -1369,7 +1449,7 @@ HB_SIZE hb_fsPipeWrite( HB_FHANDLE hPipeHandle, const void * buffer, HB_SIZE nSi
hb_fsOsError() != ( HB_ERRCODE ) EINTR ||
hb_vmRequestQuery() != 0 )
break;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else if( nTimeOut > 0 )
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
@@ -1380,8 +1460,10 @@ HB_SIZE hb_fsPipeWrite( HB_FHANDLE hPipeHandle, const void * buffer, HB_SIZE nSi
timer = timecurr;
}
}
#endif
# endif
}
#endif /* HB_HAS_POLL */
if( iResult > 0 )
{
int iFlags = -1;

View File

@@ -83,7 +83,7 @@ static int hb_Inp9x( unsigned short int usPort )
HB_TRACE( HB_TR_DEBUG, ( "hb_Inp9x(%hu)", usPort ) );
#if defined( __DMC__ )
#if defined( __DMC__ ) || ( defined( __BORLANDC__ ) && ! defined( __clang__ ) )
_DX = usPort;
__emit__(0xEC); /* ASM IN AL, DX */
@@ -121,7 +121,7 @@ static int hb_Outp9x( unsigned short int usPort, unsigned short int usVal )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_Outp9x(%hu, %hu)", usPort, usVal ) );
#if defined( __DMC__ )
#if defined( __DMC__ ) || ( defined( __BORLANDC__ ) && ! defined( __clang__ ) )
_DX = usPort;
_AL = usVal;

View File

@@ -81,6 +81,12 @@
# if defined( HB_OS_UNIX )
# include <sys/time.h>
# include <sys/types.h>
# if defined( _POSIX_C_SOURCE ) && _POSIX_C_SOURCE >= 200112L
/* use poll() instead of select() to avoid FD_SETSIZE (1024 in Linux)
file handle limit */
# define HB_HAS_POLL
# include <poll.h>
# endif
# endif
# if defined( HB_OS_HPUX )
# include <sys/modem.h>
@@ -527,16 +533,53 @@ static void hb_comSetOsError( PHB_COM pCom, HB_BOOL fError )
#if defined( HB_OS_UNIX )
static int hb_comCanRead( PHB_COM pCom, HB_MAXINT timeout )
{
struct timeval tv;
fd_set rfds;
int iResult;
#if ! defined( HB_HAS_SELECT_TIMER )
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
struct pollfd fds;
fds.fd = pCom->fd;
fds.events = POLLIN;
fds.revents = 0;
for( ;; )
{
int tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( &fds, 1, tout );
hb_comSetOsError( pCom, iResult == -1 );
if( iResult > 0 && ( fds.revents & POLLIN ) == 0 )
iResult = 0;
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_COM_IS_EINTR() ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
return iResult;
#else
struct timeval tv;
fd_set rfds;
# if ! defined( HB_HAS_SELECT_TIMER )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
# else
tv.tv_sec = ( long ) ( timeout / 1000 );
tv.tv_usec = ( long ) ( timeout % 1000 ) * 1000;
#endif
# endif
for( ;; )
{
@@ -548,22 +591,24 @@ static int hb_comCanRead( PHB_COM pCom, HB_MAXINT timeout )
tv.tv_sec = 1;
tv.tv_usec = 0;
}
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else
{
tv.tv_sec = ( long ) ( timeout / 1000 );
tv.tv_usec = ( long ) ( timeout % 1000 ) * 1000;
}
#endif
# endif
iResult = select( ( int ) ( pCom->fd + 1 ), &rfds, NULL, NULL, &tv );
if( iResult > 0 && ! FD_ISSET( pCom->fd, &rfds ) )
iResult = 0;
hb_comSetOsError( pCom, iResult == -1 );
if( iResult == 0 && timeout < 0 )
if( iResult == 0 && timeout < 0 && hb_vmRequestQuery() == 0 )
continue;
if( iResult != -1 || timeout == 0 || ! HB_COM_IS_EINTR() ||
hb_vmRequestQuery() != 0 )
break;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else if( timeout > 0 )
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
@@ -574,25 +619,62 @@ static int hb_comCanRead( PHB_COM pCom, HB_MAXINT timeout )
timer = timecurr;
}
}
#endif
# endif
}
#endif /* HB_HAS_POLL */
return iResult < 0 ? -1 :
( iResult > 0 && FD_ISSET( pCom->fd, &rfds ) ? 1 : 0 );
return iResult;
}
static int hb_comCanWrite( PHB_COM pCom, HB_MAXINT timeout )
{
struct timeval tv;
fd_set wfds;
int iResult;
#if ! defined( HB_HAS_SELECT_TIMER )
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
struct pollfd fds;
fds.fd = pCom->fd;
fds.events = POLLOUT;
fds.revents = 0;
for( ;; )
{
int tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( &fds, 1, tout );
hb_comSetOsError( pCom, iResult == -1 );
if( iResult > 0 && ( fds.revents & POLLOUT ) == 0 )
iResult = 0;
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_COM_IS_EINTR() ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
return iResult;
#else
struct timeval tv;
fd_set wfds;
# if ! defined( HB_HAS_SELECT_TIMER )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
# else
tv.tv_sec = ( long ) ( timeout / 1000 );
tv.tv_usec = ( long ) ( timeout % 1000 ) * 1000;
#endif
# endif
for( ;; )
{
@@ -604,22 +686,24 @@ static int hb_comCanWrite( PHB_COM pCom, HB_MAXINT timeout )
tv.tv_sec = 1;
tv.tv_usec = 0;
}
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else
{
tv.tv_sec = ( long ) ( timeout / 1000 );
tv.tv_usec = ( long ) ( timeout % 1000 ) * 1000;
}
#endif
# endif
iResult = select( ( int ) ( pCom->fd + 1 ), NULL, &wfds, NULL, &tv );
if( iResult > 0 && FD_ISSET( pCom->fd, &wfds ) )
iResult = 0;
hb_comSetOsError( pCom, iResult == -1 );
if( iResult == 0 && timeout < 0 )
if( iResult == 0 && timeout < 0 && hb_vmRequestQuery() == 0 )
continue;
if( iResult != -1 || timeout == 0 || ! HB_COM_IS_EINTR() ||
hb_vmRequestQuery() != 0 )
break;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
else if( timeout > 0 )
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
@@ -630,12 +714,12 @@ static int hb_comCanWrite( PHB_COM pCom, HB_MAXINT timeout )
timer = timecurr;
}
}
#endif
# endif
break;
}
#endif /* HB_HAS_POLL */
return iResult < 0 ? -1 :
( iResult > 0 && FD_ISSET( pCom->fd, &wfds ) ? 1 : 0 );
return iResult;
}
#endif

View File

@@ -58,6 +58,13 @@
# include <sys/stat.h>
# include <fcntl.h>
# include <signal.h>
# include <errno.h>
# if defined( _POSIX_C_SOURCE ) && _POSIX_C_SOURCE >= 200112L
/* use poll() instead of select() to avoid FD_SETSIZE (1024 in Linux)
file handle limit */
# define HB_HAS_POLL
# include <poll.h>
# endif
#elif defined( HB_OS_OS2 )
# define INCL_DOSERRORS
# define INCL_DOSPROCESS
@@ -1456,11 +1463,6 @@ int hb_fsProcessRun( const char * pszFileName,
#elif defined( HB_OS_UNIX ) && ! defined( HB_OS_SYMBIAN )
fd_set rfds, wfds, *prfds, *pwfds;
HB_FHANDLE fdMax;
HB_SIZE ul;
int n;
if( nStdInLen == 0 && hStdin != FS_ERROR )
{
hb_fsClose( hStdin );
@@ -1478,99 +1480,153 @@ int hb_fsProcessRun( const char * pszFileName,
for( ;; )
{
fdMax = 0;
prfds = pwfds = NULL;
if( hStdout != FS_ERROR || hStderr != FS_ERROR )
HB_BOOL fStdout, fStderr, fStdin;
HB_SIZE nLen;
int iResult;
#if defined( HB_HAS_POLL )
{
FD_ZERO( &rfds );
struct pollfd fds[ 3 ];
nfds_t nfds = 0;
if( hStdout != FS_ERROR )
{
FD_SET( hStdout, &rfds );
if( hStdout > fdMax )
fdMax = hStdout;
fds[ nfds ].fd = hStdout;
fds[ nfds ].events |= POLLIN;
fds[ nfds++ ].revents = 0;
}
if( hStderr != FS_ERROR )
{
FD_SET( hStderr, &rfds );
if( hStderr > fdMax )
fdMax = hStderr;
fds[ nfds ].fd = hStderr;
fds[ nfds ].events |= POLLIN;
fds[ nfds++ ].revents = 0;
}
prfds = &rfds;
if( hStdin != FS_ERROR )
{
fds[ nfds ].fd = hStdin;
fds[ nfds ].events |= POLLOUT;
fds[ nfds++ ].revents = 0;
}
if( nfds == 0 )
break;
iResult = poll( fds, nfds, -1 );
hb_fsSetIOError( iResult >= 0, 0 );
if( iResult == -1 && hb_fsOsError() == ( HB_ERRCODE ) EINTR &&
hb_vmRequestQuery() == 0 )
continue;
else if( iResult <= 0 )
break;
nfds = 0;
fStdout = hStdout != FS_ERROR && ( fds[ nfds++ ].revents & POLLIN ) != 0;
fStderr = hStderr != FS_ERROR && ( fds[ nfds++ ].revents & POLLIN ) != 0;
fStdin = hStdin != FS_ERROR && ( fds[ nfds++ ].revents & POLLOUT ) != 0;
}
if( hStdin != FS_ERROR )
#else
{
FD_ZERO( &wfds );
FD_SET( hStdin, &wfds );
if( hStdin > fdMax )
fdMax = hStdin;
pwfds = &wfds;
}
if( prfds == NULL && pwfds == NULL )
break;
fd_set rfds, wfds, *prfds, *pwfds;
HB_FHANDLE fdMax;
n = select( fdMax + 1, prfds, pwfds, NULL, NULL );
if( n > 0 )
fdMax = 0;
prfds = pwfds = NULL;
if( hStdout != FS_ERROR || hStderr != FS_ERROR )
{
FD_ZERO( &rfds );
if( hStdout != FS_ERROR )
{
FD_SET( hStdout, &rfds );
if( hStdout > fdMax )
fdMax = hStdout;
}
if( hStderr != FS_ERROR )
{
FD_SET( hStderr, &rfds );
if( hStderr > fdMax )
fdMax = hStderr;
}
prfds = &rfds;
}
if( hStdin != FS_ERROR )
{
FD_ZERO( &wfds );
FD_SET( hStdin, &wfds );
if( hStdin > fdMax )
fdMax = hStdin;
pwfds = &wfds;
}
if( prfds == NULL && pwfds == NULL )
break;
iResult = select( fdMax + 1, prfds, pwfds, NULL, NULL );
hb_fsSetIOError( iResult >= 0, 0 );
if( iResult == -1 && hb_fsOsError() != ( HB_ERRCODE ) EINTR &&
hb_vmRequestQuery() == 0 )
continue;
else if( iResult <= 0 )
break;
fStdout = hStdout != FS_ERROR && FD_ISSET( hStdout, &rfds );
fStderr = hStderr != FS_ERROR && FD_ISSET( hStderr, &rfds );
fStdin = hStdin != FS_ERROR && FD_ISSET( hStdin, &wfds );
}
#endif /* HB_HAS_POLL */
if( fStdout )
{
if( hStdout != FS_ERROR && FD_ISSET( hStdout, &rfds ) )
if( nOutBuf == nOutSize )
{
if( nOutBuf == nOutSize )
{
if( nOutSize == 0 )
nOutSize = HB_STD_BUFFER_SIZE;
else
nOutSize += nOutSize >> 1;
pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
}
ul = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
if( ul == 0 )
{
/* zero bytes read after positive Select()
* - writing process closed the pipe
*/
hb_fsClose( hStdout );
hStdout = FS_ERROR;
}
if( nOutSize == 0 )
nOutSize = HB_STD_BUFFER_SIZE;
else
nOutBuf += ul;
nOutSize += nOutSize >> 1;
pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
}
if( hStderr != FS_ERROR && FD_ISSET( hStderr, &rfds ) )
nLen = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
if( nLen == 0 )
{
if( nErrBuf == nErrSize )
{
if( nErrSize == 0 )
nErrSize = HB_STD_BUFFER_SIZE;
else
nErrSize += nErrSize >> 1;
pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
}
ul = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
if( ul == 0 )
{
/* zero bytes read after positive Select()
* - writing process closed the pipe
*/
hb_fsClose( hStderr );
hStderr = FS_ERROR;
}
/* zero bytes read after positive Select()
* - writing process closed the pipe
*/
hb_fsClose( hStdout );
hStdout = FS_ERROR;
}
else
nOutBuf += nLen;
}
if( fStderr )
{
if( nErrBuf == nErrSize )
{
if( nErrSize == 0 )
nErrSize = HB_STD_BUFFER_SIZE;
else
nErrBuf += ul;
nErrSize += nErrSize >> 1;
pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
}
if( hStdin != FS_ERROR && FD_ISSET( hStdin, &wfds ) )
nLen = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
if( nLen == 0 )
{
ul = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
pStdInBuf += ul;
nStdInLen -= ul;
if( nStdInLen == 0 )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
/* zero bytes read after positive Select()
* - writing process closed the pipe
*/
hb_fsClose( hStderr );
hStderr = FS_ERROR;
}
else
nErrBuf += nLen;
}
if( fStdin )
{
nLen = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
pStdInBuf += nLen;
nStdInLen -= nLen;
if( nStdInLen == 0 )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
}
else
break;
}
if( hStdin != FS_ERROR )

View File

@@ -81,6 +81,9 @@
platform supports gethostbyaddr function:
#define HB_HAS_GETHOSTBYADDR
platform supports poll() function:
#define HB_HAS_POLL
platform uses sockaddr structure which contains sa_len member:
#define HB_HAS_SOCKADDR_SA_LEN
@@ -125,6 +128,9 @@
# define HB_HAS_ADDRINFO
# define HB_HAS_NAMEINFO
# define HB_HAS_GETHOSTBYADDR
# if defined( _POSIX_C_SOURCE ) && _POSIX_C_SOURCE >= 200112L
# define HB_HAS_POLL
# endif
# endif
# if ! defined( __WATCOMC__ ) && ! defined( HB_OS_BEOS ) && ! defined( HB_OS_MINIX )
# define HB_HAS_INET6
@@ -249,6 +255,9 @@
# if defined( HB_HAS_UNIX )
# include <sys/un.h>
# endif
# if defined( HB_HAS_POLL )
# include <poll.h>
# endif
# include <netinet/tcp.h>
# if ! ( defined( HB_OS_LINUX ) && defined( __WATCOMC__ ) )
# include <net/if.h>
@@ -1483,13 +1492,50 @@ static int hb_socketTransType( int type, int *err )
static int hb_socketSelectRD( HB_SOCKET sd, HB_MAXINT timeout )
{
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
int iResult, iError, tout;
struct pollfd fds;
fds.fd = sd;
fds.events = POLLIN;
fds.revents = 0;
for( ;; )
{
tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( &fds, 1, tout );
iError = iResult >= 0 ? 0 : HB_SOCK_GETERROR();
hb_socketSetOsError( iError );
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_SOCK_IS_EINTR( iError ) ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
return iResult < 0 ? -1 :
( iResult > 0 && ( fds.revents & POLLIN ) != 0 ? 1 : 0 );
#else
struct timeval tv, * ptv;
fd_set rfds;
int iResult, iError;
#if ! defined( HB_HAS_SELECT_TIMER )
# if ! defined( HB_HAS_SELECT_TIMER )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
#endif
# endif
if( timeout >= 0 )
{
@@ -1510,9 +1556,9 @@ static int hb_socketSelectRD( HB_SOCKET sd, HB_MAXINT timeout )
hb_socketSetOsError( iError );
if( iResult == -1 && timeout > 0 && HB_SOCK_IS_EINTR( iError ) &&
hb_vmRequestQuery() == 0 )
#if defined( HB_HAS_SELECT_TIMER )
# if defined( HB_HAS_SELECT_TIMER )
continue;
#else
# else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
@@ -1527,16 +1573,54 @@ static int hb_socketSelectRD( HB_SOCKET sd, HB_MAXINT timeout )
}
}
}
#endif
# endif
break;
}
return iResult < 0 ? -1 :
( iResult > 0 && FD_ISSET( ( HB_SOCKET_T ) sd, &rfds ) ? 1 : 0 );
#endif /* HB_HAS_POLL */
}
static int hb_socketSelectWR( HB_SOCKET sd, HB_MAXINT timeout )
{
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
int iResult, iError, tout;
struct pollfd fds;
fds.fd = sd;
fds.events = POLLOUT;
fds.revents = 0;
for( ;; )
{
tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( &fds, 1, tout );
iError = iResult >= 0 ? 0 : HB_SOCK_GETERROR();
hb_socketSetOsError( iError );
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_SOCK_IS_EINTR( iError ) ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
return iResult < 0 ? -1 :
( iResult > 0 && ( fds.revents & POLLOUT ) != 0 ? 1 : 0 );
#else
struct timeval tv, * ptv;
fd_set wfds;
int iResult, iError;
@@ -1587,10 +1671,60 @@ static int hb_socketSelectWR( HB_SOCKET sd, HB_MAXINT timeout )
return iResult < 0 ? -1 :
( iResult > 0 && FD_ISSET( ( HB_SOCKET_T ) sd, &wfds ) ? 1 : 0 );
#endif /* HB_HAS_POLL */
}
static int hb_socketSelectWRE( HB_SOCKET sd, HB_MAXINT timeout )
{
#if defined( HB_HAS_POLL )
HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
int iResult, iError, tout;
struct pollfd fds;
fds.fd = sd;
fds.events = POLLOUT;
fds.revents = 0;
for( ;; )
{
tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( &fds, 1, tout );
iError = iResult >= 0 ? 0 : HB_SOCK_GETERROR();
hb_socketSetOsError( iError );
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_SOCK_IS_EINTR( iError ) ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
if( iResult > 0 && ( fds.revents & POLLOUT ) != 0 )
{
socklen_t len = sizeof( iError );
if( getsockopt( sd, SOL_SOCKET, SO_ERROR, ( char * ) &iError, &len ) != 0 )
{
iResult = -1;
iError = HB_SOCK_GETERROR();
}
else if( iError != 0 )
iResult = -1;
hb_socketSetOsError( iError );
}
return iResult < 0 ? -1 :
( iResult > 0 && ( fds.revents & POLLOUT ) != 0 ? 1 : 0 );
#else
struct timeval tv, * ptv;
fd_set wfds, * pefds;
@@ -1682,6 +1816,7 @@ static int hb_socketSelectWRE( HB_SOCKET sd, HB_MAXINT timeout )
return iResult < 0 ? -1 :
( iResult > 0 && FD_ISSET( ( HB_SOCKET_T ) sd, &wfds ) ? 1 : 0 );
#endif /* HB_HAS_POLL */
}
int hb_socketGetAddrFamily( const void * pSockAddr, unsigned len )
@@ -2782,11 +2917,149 @@ static HB_SOCKET s_socketSelectCallback( PHB_ITEM pItem )
return sd;
}
#if defined( HB_HAS_POLL )
static int s_socketPollCheck( HB_SOCKET sd, struct pollfd * pfds, nfds_t nfds )
{
nfds_t npos;
for( npos = 0; npos < nfds; ++npos )
{
if( pfds[ npos ].fd == sd )
return ( int ) npos;
}
return -1;
}
#endif /* HB_HAS_POLL */
int hb_socketSelect( PHB_ITEM pArrayRD, HB_BOOL fSetRD,
PHB_ITEM pArrayWR, HB_BOOL fSetWR,
PHB_ITEM pArrayEX, HB_BOOL fSetEX,
HB_MAXINT timeout, HB_SOCKET_FUNC pFunc )
{
#if defined( HB_HAS_POLL )
HB_SOCKET sd;
HB_SIZE nLen, nPos, ul;
int iResult, iError, tout, iPos, i;
HB_MAXUINT timer;
PHB_ITEM pItemSets[ 3 ];
HB_BOOL pSet[ 3 ];
int pEvents[ 3 ];
struct pollfd * pfds = NULL;
nfds_t nfds = 0, ncnt = 0;
if( pFunc == NULL )
pFunc = s_socketSelectCallback;
pItemSets[ 0 ] = pArrayRD;
pItemSets[ 1 ] = pArrayWR;
pItemSets[ 2 ] = pArrayEX;
pSet[ 0 ] = fSetRD;
pSet[ 1 ] = fSetWR;
pSet[ 2 ] = fSetEX;
pEvents[ 0 ] = POLLIN;
pEvents[ 1 ] = POLLOUT;
pEvents[ 2 ] = POLLERR | POLLHUP | POLLNVAL;
for( i = 0; i < 3; i++ )
{
if( pItemSets[ i ] )
ncnt += ( nfds_t ) hb_arrayLen( pItemSets[ i ] );
}
if( ncnt > 0 )
pfds = ( struct pollfd * ) hb_xgrab( ncnt * sizeof( struct pollfd * ) );
for( i = 0; i < 3; i++ )
{
nLen = pItemSets[ i ] ? hb_arrayLen( pItemSets[ i ] ) : 0;
for( ul = 1; ul <= nLen && nfds < ncnt; ul++ )
{
sd = pFunc( hb_arrayGetItemPtr( pItemSets[ i ], ul ) );
if( sd != HB_NO_SOCKET )
{
iPos = s_socketPollCheck( sd, pfds, nfds );
if( iPos < 0 )
{
iPos = ( int ) nfds++;
pfds[ iPos ].fd = sd;
pfds[ iPos ].revents = 0;
}
if( i < 2 )
pfds[ iPos ].events |= pEvents[ i ];
}
}
}
timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
if( hb_vmRequestQuery() == 0 )
{
hb_vmUnlock();
for( ;; )
{
tout = timeout < 0 || timeout > 1000 ? 1000 : ( int ) timeout;
iResult = poll( pfds, nfds, tout );
iError = iResult >= 0 ? 0 : HB_SOCK_GETERROR();
hb_socketSetOsError( iError );
if( ( ( iResult == 0 && ( timeout < 0 || timeout > 1000 ) ) ||
( iResult == -1 && timeout != 0 && HB_SOCK_IS_EINTR( iError ) ) ) &&
hb_vmRequestQuery() == 0 )
{
if( timeout < 0 )
continue;
else
{
HB_MAXUINT timecurr = hb_dateMilliSeconds();
if( timecurr > timer )
{
timeout -= timecurr - timer;
if( timeout > 0 )
continue;
}
}
}
break;
}
hb_vmLock();
for( i = 0; i < 3; i++ )
{
if( pItemSets[ i ] && pSet[ i ] )
{
nPos = 0;
if( iResult > 0 )
{
nLen = hb_arrayLen( pItemSets[ i ] );
for( ul = 1; ul <= nLen; ul++ )
{
sd = pFunc( hb_arrayGetItemPtr( pItemSets[ i ], ul ) );
if( sd != HB_NO_SOCKET )
{
iPos = s_socketPollCheck( sd, pfds, nfds );
if( iPos >= 0 && ( pfds[ iPos ].revents & pEvents[ i ] ) != 0 )
{
if( ++nPos != ul )
hb_itemCopy( hb_arrayGetItemPtr( pItemSets[ i ], nPos ),
hb_arrayGetItemPtr( pItemSets[ i ], ul ) );
}
}
}
}
hb_arraySize( pItemSets[ i ], nPos );
}
}
}
else
{
hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
iResult = -1;
}
if( pfds )
hb_xfree( pfds );
return iResult;
#else
HB_SOCKET maxsd, sd;
int i, ret;
HB_SIZE nLen, nPos, ul;
@@ -2877,6 +3150,7 @@ int hb_socketSelect( PHB_ITEM pArrayRD, HB_BOOL fSetRD,
}
return ret;
#endif /* HB_HAS_POLL */
}