public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] FreeBSD problem with UDP sockets
@ 2004-08-12  3:10 David Brennan
  2004-08-12  8:23 ` Andrew Lunn
  0 siblings, 1 reply; 4+ messages in thread
From: David Brennan @ 2004-08-12  3:10 UTC (permalink / raw)
  To: eCos Discussion List

I am currently having a problem with FreeBSD sockets.
Setup: i386-pc 82559, latest snapshot from snapshot service.

Background: Our application uses a UDP communication protocol over 2
sockets. Each one is a validated half duplex channel. That is the
sendSocket will receive acknowledgments of previous sends and recvSocket
will send acknowledgments of previous receives.
Implementation: I open two (UDP) sockets (sendSocket, and recvSocket).
I then do a select on either port. Once I receive a packet, I query each
socket to see if FD_ISSET. When I send a packet (from extenal host) to 
the second socket checked (recvSocket), the first socket returns with 
FD_ISSET, then my code goes into a blocking recvfrom and hangs since no 
data was actually on that socket..

Here are code snippets showing how the sockets are created, selected,
then received. This code has worked fine in pSOS and VxWorks, so I don't
think there is a fundamental problem here, unless there is some secret
to eCos implementation of BSD sockets.

Any help would be greatly appreciated.

David Brennan

// Two sockets are created (sendSocket, recvSocket):

    //  Create the socket
    socketM = socket(AF_INET, SOCK_DGRAM, 0);

    if (socketM < 0)
    {
        FATALSYS(("Cannot create socket"));
    }

    sockAddrInT localAddr((inAddrT((ULong) INADDR_ANY)), localPortI);

    //  Bind the socket to local address and port number
    int err = bind(socketM, &localAddr, sizeof(sockaddr_in));
    if( err < 0 )
    {
        str32T addrS;
        FATALSYS(("Can't bind socket to local IP port %s:%d",
                  localAddr.AddrStr(addrS.CharP()),
                  localPortI
                ));
    }


// Sockets are waited on for receive data (infinite wait):

    fd_set readMask;

    FD_ZERO(&readMask);
    pAssert(InRange(sendSocket, 0, FD_SETSIZE-1));           // Limit to
keep FD_SET from writing out of readfds
    pAssert(InRange(recvSocket, 0, FD_SETSIZE-1));           // Limit to
keep FD_SET from writing out of readfds
    FD_SET(sendSocket, &readMask);
    FD_SET(recvSocket, &readMask);

    //  Use select to wait for input from either the send or receive
sockets
    long err = select(FD_SETSIZE, &readMask, NULL, NULL, NULL);

    if( err < 0 )
    {
        FATALSYS(("select()=%d ", err));
        return( 0 );
    }

// Once select() returns successfully, check each socket (sendSocket,
recvSocket) for data:

    // Set of socket/file descriptors
    fd_set readfds;

    // Clear all socket selections from the read file descriptor set
    FD_ZERO(&readfds);

    // Select only this socket in the read file descriptor set
    // Limit to keep FD_SET from writing out of readfds
    pAssert(InOrderedRange(socketM, 0, FD_SETSIZE-1));
    FD_SET(socketM, &readfds);

    // Create a wait timeout
    timeval waitTime;
    waitTime.tv_sec = 0L;
    waitTime.tv_usec = 0;

    // Use select on this socket to determine if there is pending read data
    int result = select(FD_SETSIZE,
                        &readfds,
                        NULL,
                        NULL,
                        &waitTime
                       );

    if( result < 0 )
    {
        FATALSYS(("Error in: select(%d)", socketM));
    }

    int isSet = FD_ISSET(socketM, &readfds);

    if( isSet != 0 )
    {
        respPktT respPkt;
        sockAddrInT sendersAddr;

        recvfrom( socketM,
                  (char *) (&respPkt),
                  sizeof(respPkt),
                  0,                      // flags
                  (sockaddr *) (&sendersAddr),
                  (socklen_t) sizeof(sendersAddr)
                )
    }


Exported ecos.ecc:

cdl_savefile_version 1;
cdl_savefile_command cdl_savefile_version {};
cdl_savefile_command cdl_savefile_command {};
cdl_savefile_command cdl_configuration { description hardware template
package };
cdl_savefile_command cdl_package { value_source user_value wizard_value
inferred_value };
cdl_savefile_command cdl_component { value_source user_value
wizard_value inferred_value };
cdl_savefile_command cdl_option { value_source user_value wizard_value
inferred_value };
cdl_savefile_command cdl_interface { value_source user_value
wizard_value inferred_value };

cdl_configuration eCos {
    description "" ;
    hardware    pc ;
    template    default ;
    package -hardware CYGPKG_HAL_I386 current ;
    package -hardware CYGPKG_HAL_I386_GENERIC current ;
    package -hardware CYGPKG_HAL_I386_PC current ;
    package -hardware CYGPKG_HAL_I386_PCMB current ;
    package -hardware CYGPKG_IO_PCI current ;
    package -hardware CYGPKG_IO_SERIAL_GENERIC_16X5X current ;
    package -hardware CYGPKG_IO_SERIAL_I386_PC current ;
    package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ;
    package -hardware CYGPKG_DEVS_ETH_I386_PC_I82559 current ;
    package -hardware CYGPKG_DEVICES_WALLCLOCK_DALLAS_DS12887 current ;
    package -hardware CYGPKG_DEVICES_WALLCLOCK_I386_PC current ;
    package -template CYGPKG_HAL current ;
    package -template CYGPKG_IO current ;
    package -template CYGPKG_IO_SERIAL current ;
    package -template CYGPKG_INFRA current ;
    package -template CYGPKG_KERNEL current ;
    package -template CYGPKG_MEMALLOC current ;
    package -template CYGPKG_ISOINFRA current ;
    package -template CYGPKG_LIBC current ;
    package -template CYGPKG_LIBC_I18N current ;
    package -template CYGPKG_LIBC_SETJMP current ;
    package -template CYGPKG_LIBC_SIGNALS current ;
    package -template CYGPKG_LIBC_STARTUP current ;
    package -template CYGPKG_LIBC_STDIO current ;
    package -template CYGPKG_LIBC_STDLIB current ;
    package -template CYGPKG_LIBC_STRING current ;
    package -template CYGPKG_LIBC_TIME current ;
    package -template CYGPKG_LIBM current ;
    package -template CYGPKG_IO_WALLCLOCK current ;
    package -template CYGPKG_ERROR current ;
    package CYGPKG_BLOCK_LIB current ;
    package CYGPKG_IO_FILEIO current ;
    package CYGPKG_LINUX_COMPAT current ;
    package CYGPKG_FS_FAT current ;
    package CYGPKG_IO_ETH_DRIVERS current ;
    package CYGPKG_NET current ;
    package CYGPKG_NET_FREEBSD_STACK current ;
    package CYGPKG_POSIX current ;
};

cdl_component CYGPKG_INFRA_DEBUG {
    user_value 1
};

cdl_option CYGIMP_KERNEL_SCHED_SORTED_QUEUES {
    inferred_value 1
};

cdl_option CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE {
    inferred_value 1
};

cdl_component CYGSEM_KERNEL_SCHED_ASR_SUPPORT {
    inferred_value 1
};

cdl_option CYGSEM_KERNEL_SCHED_ASR_GLOBAL {
    inferred_value 1
};

cdl_option CYGBLD_ISO_CTYPE_HEADER {
    inferred_value 1 <cyg/libc/i18n/ctype.inl>
};

cdl_option CYGBLD_ISO_ERRNO_CODES_HEADER {
    inferred_value 1 <cyg/error/codes.h>
};

cdl_option CYGBLD_ISO_ERRNO_HEADER {
    inferred_value 1 <cyg/error/errno.h>
};

cdl_option CYGBLD_ISO_STDIO_FILETYPES_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_STREAMS_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_FILEOPS_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_FILEACCESS_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_FORMATTED_IO_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_CHAR_IO_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_DIRECT_IO_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_FILEPOS_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDIO_ERROR_HEADER {
    inferred_value 1 <cyg/libc/stdio/stdio.h>
};

cdl_option CYGBLD_ISO_STDLIB_STRCONV_HEADER {
    inferred_value 1 <cyg/libc/stdlib/atox.inl>
};

cdl_option CYGBLD_ISO_STDLIB_ABS_HEADER {
    inferred_value 1 <cyg/libc/stdlib/abs.inl>
};

cdl_option CYGBLD_ISO_STDLIB_DIV_HEADER {
    inferred_value 1 <cyg/libc/stdlib/div.inl>
};

cdl_option CYGBLD_ISO_STRERROR_HEADER {
    inferred_value 1 <cyg/error/strerror.h>
};

cdl_option CYGBLD_ISO_STRTOK_R_HEADER {
    inferred_value 1 <cyg/libc/string/string.h>
};

cdl_option CYGBLD_ISO_STRING_LOCALE_FUNCS_HEADER {
    inferred_value 1 <cyg/libc/string/string.h>
};

cdl_option CYGBLD_ISO_STRING_BSD_FUNCS_HEADER {
    inferred_value 1 <cyg/libc/string/bsdstring.h>
};

cdl_option CYGBLD_ISO_STRING_MEMFUNCS_HEADER {
    inferred_value 1 <cyg/libc/string/string.h>
};

cdl_option CYGBLD_ISO_STRING_STRFUNCS_HEADER {
    inferred_value 1 <cyg/libc/string/string.h>
};

cdl_option CYGBLD_ISO_POSIX_CLOCK_TYPES_HEADER {
    inferred_value 1 <cyg/posix/time.h>
};

cdl_option CYGBLD_ISO_C_TIME_TYPES_HEADER {
    inferred_value 1 <cyg/libc/time/time.h>
};

cdl_option CYGBLD_ISO_POSIX_CLOCKS_HEADER {
    inferred_value 1 <cyg/posix/time.h>
};

cdl_option CYGBLD_ISO_C_CLOCK_FUNCS_HEADER {
    inferred_value 1 <cyg/libc/time/time.h>
};

cdl_option CYGBLD_ISO_SIGNAL_NUMBERS_HEADER {
    inferred_value 1 <cyg/libc/signals/signal.h>
};

cdl_option CYGBLD_ISO_SIGNAL_IMPL_HEADER {
    inferred_value 1 <cyg/libc/signals/signal.h>
};

cdl_option CYGBLD_ISO_SETJMP_HEADER {
    inferred_value 1 <cyg/libc/setjmp/setjmp.h>
};

cdl_option CYGBLD_ISO_SIGSETJMP_HEADER {
    inferred_value 1 <cyg/posix/sigsetjmp.h>
};

cdl_option CYGBLD_ISO_DIRENT_HEADER {
    inferred_value 1 <cyg/fileio/dirent.h>
};

cdl_option CYGBLD_ISO_PTHREADTYPES_HEADER {
    inferred_value 1 <cyg/posix/types.h>
};

cdl_option CYGBLD_ISO_PMUTEXTYPES_HEADER {
    inferred_value 1 <cyg/posix/muttypes.h>
};

cdl_option CYGBLD_ISO_BSDTYPES_HEADER {
    inferred_value 1 <sys/bsdtypes.h>
};

cdl_option CYGBLD_ISO_UTSNAME_HEADER {
    inferred_value 1 <cyg/posix/utsname.h>
};

cdl_option CYGBLD_ISO_SEMAPHORES_HEADER {
    inferred_value 1 <cyg/posix/semaphore.h>
};

cdl_option CYGBLD_ISO_PTHREAD_IMPL_HEADER {
    inferred_value 1 <cyg/posix/pthread.h>
};

cdl_option CYGBLD_ISO_PTHREAD_MUTEX_HEADER {
    inferred_value 1 <cyg/posix/mutex.h>
};

cdl_option CYGBLD_ISO_POSIX_LIMITS_HEADER {
    inferred_value 1 <cyg/posix/limits.h>
};

cdl_option CYGBLD_ISO_OPEN_MAX_HEADER {
    inferred_value 1 <cyg/fileio/limits.h>
};

cdl_option CYGBLD_ISO_NAME_MAX_HEADER {
    inferred_value 1 <cyg/fileio/limits.h>
};

cdl_option CYGBLD_ISO_NETDB_PROTO_HEADER {
    inferred_value 1 <net/netdb.h>
};

cdl_option CYGBLD_ISO_NETDB_SERV_HEADER {
    inferred_value 1 <net/netdb.h>
};

cdl_option CYGPKG_POSIX_TIMERS {
    inferred_value 0
};

cdl_component CYGPKG_POSIX_SIGNALS {
    inferred_value 0
};






-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [ECOS] FreeBSD problem with UDP sockets
  2004-08-12  3:10 [ECOS] FreeBSD problem with UDP sockets David Brennan
@ 2004-08-12  8:23 ` Andrew Lunn
  2004-08-13  3:45   ` David Brennan
  2004-08-18 20:58   ` Bart Veer
  0 siblings, 2 replies; 4+ messages in thread
From: Andrew Lunn @ 2004-08-12  8:23 UTC (permalink / raw)
  To: David Brennan; +Cc: eCos Discussion List

On Wed, Aug 11, 2004 at 08:10:46PM -0700, David Brennan wrote:
> I am currently having a problem with FreeBSD sockets.
> Setup: i386-pc 82559, latest snapshot from snapshot service.
> 
> Background: Our application uses a UDP communication protocol over 2
> sockets. Each one is a validated half duplex channel. That is the
> sendSocket will receive acknowledgments of previous sends and recvSocket
> will send acknowledgments of previous receives.
> Implementation: I open two (UDP) sockets (sendSocket, and recvSocket).
> I then do a select on either port. Once I receive a packet, I query each
> socket to see if FD_ISSET. When I send a packet (from extenal host) to 
> the second socket checked (recvSocket), the first socket returns with 
> FD_ISSET, then my code goes into a blocking recvfrom and hangs since no 
> data was actually on that socket..
> 
> Here are code snippets showing how the sockets are created, selected,
> then received. This code has worked fine in pSOS and VxWorks, so I don't
> think there is a fundamental problem here, unless there is some secret
> to eCos implementation of BSD sockets.
> 
> Any help would be greatly appreciated.
> 
> David Brennan
> 
> // Two sockets are created (sendSocket, recvSocket):
> 
>    //  Create the socket
>    socketM = socket(AF_INET, SOCK_DGRAM, 0);
> 
>    if (socketM < 0)
>    {
>        FATALSYS(("Cannot create socket"));
>    }
> 
>    sockAddrInT localAddr((inAddrT((ULong) INADDR_ANY)), localPortI);
> 
>    //  Bind the socket to local address and port number
>    int err = bind(socketM, &localAddr, sizeof(sockaddr_in));
>    if( err < 0 )
>    {
>        str32T addrS;
>        FATALSYS(("Can't bind socket to local IP port %s:%d",
>                  localAddr.AddrStr(addrS.CharP()),
>                  localPortI
>                ));
>    }
> 

So the above code creates socketM. Fine.
> 
> // Sockets are waited on for receive data (infinite wait):
> 
>    fd_set readMask;
> 
>    FD_ZERO(&readMask);
>    pAssert(InRange(sendSocket, 0, FD_SETSIZE-1));           // Limit to
> keep FD_SET from writing out of readfds
>    pAssert(InRange(recvSocket, 0, FD_SETSIZE-1));           // Limit to
> keep FD_SET from writing out of readfds
>    FD_SET(sendSocket, &readMask);
>    FD_SET(recvSocket, &readMask);
> 
>    //  Use select to wait for input from either the send or receive
> sockets
>    long err = select(FD_SETSIZE, &readMask, NULL, NULL, NULL);

Here you are using sendSocket and recvSocket which we have not seen
created. If we get passed select we know that one of these two sockets
has data on them.

 
>    if( err < 0 )
>    {
>        FATALSYS(("select()=%d ", err));
>        return( 0 );
>    }
> 
> // Once select() returns successfully, check each socket (sendSocket,
> recvSocket) for data:
> 
>    // Set of socket/file descriptors
>    fd_set readfds;
> 
>    // Clear all socket selections from the read file descriptor set
>    FD_ZERO(&readfds);
> 
>    // Select only this socket in the read file descriptor set
>    // Limit to keep FD_SET from writing out of readfds
>    pAssert(InOrderedRange(socketM, 0, FD_SETSIZE-1));
>    FD_SET(socketM, &readfds);
> 
>    // Create a wait timeout
>    timeval waitTime;
>    waitTime.tv_sec = 0L;
>    waitTime.tv_usec = 0;
> 
>    // Use select on this socket to determine if there is pending read data
>    int result = select(FD_SETSIZE,
>                        &readfds,
>                        NULL,
>                        NULL,
>                        &waitTime
>                       );

Now we are back to socketM.

What is not clear for me is the relationship between sendSocket,
recvSocket and socketM. 

>    if( result < 0 )
>    {
>        FATALSYS(("Error in: select(%d)", socketM));
>    }
> 
>    int isSet = FD_ISSET(socketM, &readfds);

Here is your problem. With passing {0,0} for waitTime, you are doing a
poll. If there is nothing to receive on the socket, select will return
0, but it is not updating the readfds. Read the code in
packages/io/fileio/current/src/select.cxx.

This might be an eCos bug. It might not be as well.  The Posix
standard at not 100% clear on this issue when i read
it. http://www.opengroup.org/onlinepubs/009695399/toc.htm

    On failure, the objects pointed to by the readfds, writefds, and
    errorfds arguments shall not be modified. If the timeout interval
    expires without the specified condition being true for any of the
    specified file descriptors, the objects pointed to by the readfds,
    writefds, and errorfds arguments shall have all bits set to 0.

When you have passed a timeout of {0,0} you are doing a poll. So the
timeout has not expired. However, we are not returning an error code
so it could also be said we are not in the failure case either.

To make your code work with eCos, check to see if the return value is
> 0. 


> 
>    if( isSet != 0 )
>    {
>        respPktT respPkt;
>        sockAddrInT sendersAddr;
> 
>        recvfrom( socketM,
>                  (char *) (&respPkt),
>                  sizeof(respPkt),
>                  0,                      // flags
>                  (sockaddr *) (&sendersAddr),
>                  (socklen_t) sizeof(sendersAddr)
>                )
>    }


        Andrew

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [ECOS] FreeBSD problem with UDP sockets
  2004-08-12  8:23 ` Andrew Lunn
@ 2004-08-13  3:45   ` David Brennan
  2004-08-18 20:58   ` Bart Veer
  1 sibling, 0 replies; 4+ messages in thread
From: David Brennan @ 2004-08-13  3:45 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: eCos Discussion List

Thanks Andrew, that did the trick. I'm still not sure it is "correct". 
But I'm not an expert at interpreting standards.

David Brennan

Andrew Lunn wrote:

>On Wed, Aug 11, 2004 at 08:10:46PM -0700, David Brennan wrote:
>  
>
>>I am currently having a problem with FreeBSD sockets.
>>Setup: i386-pc 82559, latest snapshot from snapshot service.
>>
>>Background: Our application uses a UDP communication protocol over 2
>>sockets. Each one is a validated half duplex channel. That is the
>>sendSocket will receive acknowledgments of previous sends and recvSocket
>>will send acknowledgments of previous receives.
>>Implementation: I open two (UDP) sockets (sendSocket, and recvSocket).
>>I then do a select on either port. Once I receive a packet, I query each
>>socket to see if FD_ISSET. When I send a packet (from extenal host) to 
>>the second socket checked (recvSocket), the first socket returns with 
>>FD_ISSET, then my code goes into a blocking recvfrom and hangs since no 
>>data was actually on that socket..
>>
>>Here are code snippets showing how the sockets are created, selected,
>>then received. This code has worked fine in pSOS and VxWorks, so I don't
>>think there is a fundamental problem here, unless there is some secret
>>to eCos implementation of BSD sockets.
>>
>>Any help would be greatly appreciated.
>>
>>David Brennan
>>
>>// Two sockets are created (sendSocket, recvSocket):
>>
>>   //  Create the socket
>>   socketM = socket(AF_INET, SOCK_DGRAM, 0);
>>
>>   if (socketM < 0)
>>   {
>>       FATALSYS(("Cannot create socket"));
>>   }
>>
>>   sockAddrInT localAddr((inAddrT((ULong) INADDR_ANY)), localPortI);
>>
>>   //  Bind the socket to local address and port number
>>   int err = bind(socketM, &localAddr, sizeof(sockaddr_in));
>>   if( err < 0 )
>>   {
>>       str32T addrS;
>>       FATALSYS(("Can't bind socket to local IP port %s:%d",
>>                 localAddr.AddrStr(addrS.CharP()),
>>                 localPortI
>>               ));
>>   }
>>
>>    
>>
>
>So the above code creates socketM. Fine.
>  
>
>>// Sockets are waited on for receive data (infinite wait):
>>
>>   fd_set readMask;
>>
>>   FD_ZERO(&readMask);
>>   pAssert(InRange(sendSocket, 0, FD_SETSIZE-1));           // Limit to
>>keep FD_SET from writing out of readfds
>>   pAssert(InRange(recvSocket, 0, FD_SETSIZE-1));           // Limit to
>>keep FD_SET from writing out of readfds
>>   FD_SET(sendSocket, &readMask);
>>   FD_SET(recvSocket, &readMask);
>>
>>   //  Use select to wait for input from either the send or receive
>>sockets
>>   long err = select(FD_SETSIZE, &readMask, NULL, NULL, NULL);
>>    
>>
>
>Here you are using sendSocket and recvSocket which we have not seen
>created. If we get passed select we know that one of these two sockets
>has data on them.
>
> 
>  
>
>>   if( err < 0 )
>>   {
>>       FATALSYS(("select()=%d ", err));
>>       return( 0 );
>>   }
>>
>>// Once select() returns successfully, check each socket (sendSocket,
>>recvSocket) for data:
>>
>>   // Set of socket/file descriptors
>>   fd_set readfds;
>>
>>   // Clear all socket selections from the read file descriptor set
>>   FD_ZERO(&readfds);
>>
>>   // Select only this socket in the read file descriptor set
>>   // Limit to keep FD_SET from writing out of readfds
>>   pAssert(InOrderedRange(socketM, 0, FD_SETSIZE-1));
>>   FD_SET(socketM, &readfds);
>>
>>   // Create a wait timeout
>>   timeval waitTime;
>>   waitTime.tv_sec = 0L;
>>   waitTime.tv_usec = 0;
>>
>>   // Use select on this socket to determine if there is pending read data
>>   int result = select(FD_SETSIZE,
>>                       &readfds,
>>                       NULL,
>>                       NULL,
>>                       &waitTime
>>                      );
>>    
>>
>
>Now we are back to socketM.
>
>What is not clear for me is the relationship between sendSocket,
>recvSocket and socketM. 
>
>  
>
>>   if( result < 0 )
>>   {
>>       FATALSYS(("Error in: select(%d)", socketM));
>>   }
>>
>>   int isSet = FD_ISSET(socketM, &readfds);
>>    
>>
>
>Here is your problem. With passing {0,0} for waitTime, you are doing a
>poll. If there is nothing to receive on the socket, select will return
>0, but it is not updating the readfds. Read the code in
>packages/io/fileio/current/src/select.cxx.
>
>This might be an eCos bug. It might not be as well.  The Posix
>standard at not 100% clear on this issue when i read
>it. http://www.opengroup.org/onlinepubs/009695399/toc.htm
>
>    On failure, the objects pointed to by the readfds, writefds, and
>    errorfds arguments shall not be modified. If the timeout interval
>    expires without the specified condition being true for any of the
>    specified file descriptors, the objects pointed to by the readfds,
>    writefds, and errorfds arguments shall have all bits set to 0.
>
>When you have passed a timeout of {0,0} you are doing a poll. So the
>timeout has not expired. However, we are not returning an error code
>so it could also be said we are not in the failure case either.
>
>To make your code work with eCos, check to see if the return value is
>  
>
>>0. 
>>    
>>
>
>
>  
>
>>   if( isSet != 0 )
>>   {
>>       respPktT respPkt;
>>       sockAddrInT sendersAddr;
>>
>>       recvfrom( socketM,
>>                 (char *) (&respPkt),
>>                 sizeof(respPkt),
>>                 0,                      // flags
>>                 (sockaddr *) (&sendersAddr),
>>                 (socklen_t) sizeof(sendersAddr)
>>               )
>>   }
>>    
>>
>
>
>        Andrew
>
>  
>

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [ECOS] FreeBSD problem with UDP sockets
  2004-08-12  8:23 ` Andrew Lunn
  2004-08-13  3:45   ` David Brennan
@ 2004-08-18 20:58   ` Bart Veer
  1 sibling, 0 replies; 4+ messages in thread
From: Bart Veer @ 2004-08-18 20:58 UTC (permalink / raw)
  To: andrew; +Cc: eCos, ecos-discuss

>>>>> "Andrew" == Andrew Lunn <andrew@lunn.ch> writes:

    >> if( result < 0 )
    >> {
    >> FATALSYS(("Error in: select(%d)", socketM));
    >> }
    >> 
    >> int isSet = FD_ISSET(socketM, &readfds);

    Andrew> Here is your problem. With passing {0,0} for waitTime, you
    Andrew> are doing a poll. If there is nothing to receive on the
    Andrew> socket, select will return 0, but it is not updating the
    Andrew> readfds. Read the code in
    Andrew> packages/io/fileio/current/src/select.cxx.

    Andrew> This might be an eCos bug. It might not be as well.  The Posix
    Andrew> standard at not 100% clear on this issue when i read
    Andrew> it. http://www.opengroup.org/onlinepubs/009695399/toc.htm

    Andrew>     On failure, the objects pointed to by the readfds, writefds, and
    Andrew>     errorfds arguments shall not be modified. If the timeout interval
    Andrew>     expires without the specified condition being true for any of the
    Andrew>     specified file descriptors, the objects pointed to by the readfds,
    Andrew>     writefds, and errorfds arguments shall have all bits set to 0.

    Andrew> When you have passed a timeout of {0,0} you are doing a
    Andrew> poll. So the timeout has not expired. However, we are not
    Andrew> returning an error code so it could also be said we are
    Andrew> not in the failure case either.

From my reading of the standard, specifically the "Return Value"
section, a poll is not a failure condition:

    Upon successful completion, the pselect() and select() functions
    shall return the total number of bits set in the bit masks.
    Otherwise, -1 shall be returned, and errno shall be set to
    indicate the error.

Since in this case we are not returning -1 it is not a failure, and
hence the fd_sets should be cleared. There is also some relevant text
in the Linux select_tut man page:

    If select timed out, then the file descriptors sets should be all
    empty (but may not be on some systems). However the return value
    will definitely be zero.

That man page is not authorative, but does suggest that clearing the
fd_sets is the right thing to do even though not all systems work that
way.

I think the current eCos behaviour is actually more sensible because
it means you only need to reset the fd_sets when there has been I/O,
not after every unsuccessful poll. But the standard says otherwise.

The following (untested) would probably fix the problem, but I'll
leave it to Nick to decide what to about it.

Bart

Index: select.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/fileio/current/src/select.cxx,v
retrieving revision 1.12
diff -u -r1.12 select.cxx
--- select.cxx	2 Aug 2004 11:24:48 -0000	1.12
+++ select.cxx	18 Aug 2004 20:54:16 -0000
@@ -206,7 +206,7 @@
         if( error )
             break;
         
-        if (num)
+        if (num || (0 == ticks))
         {
             // Found something, update user's sets
             if (in)  FD_COPY( &in_res, in );
@@ -248,13 +248,6 @@
                 // Nothing found, see if we want to wait
                 if (tv)
                 {
-                    // Special case of "poll"
-                    if (ticks == 0)
-                    {
-                        error = EAGAIN;
-                        break;
-                    }
-
                     ticks += Cyg_Clock::real_time_clock->current_value();
                 
                     if( !selwait.wait( ticks ) )

-- 
Bart Veer                       eCos Configuration Architect
http://www.ecoscentric.com/     The eCos and RedBoot experts

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-08-18 20:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-12  3:10 [ECOS] FreeBSD problem with UDP sockets David Brennan
2004-08-12  8:23 ` Andrew Lunn
2004-08-13  3:45   ` David Brennan
2004-08-18 20:58   ` Bart Veer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).