Hi Eric,

It looks like on windows, apr_pollset_poll() sits on top of select().  I'm new to APR, so excuse me if there is some other way of doing this. However, on windows, I tried the following (program below) to catch the interrupt by installing a signal handler that then writes to a socket.  This acts to notify select() that an interrupt has occurred.

What you could do is add your UDP socket to the pollset as well.  This way, on return from the apr_pollset_poll() you test for either (1) timeout, (2) interrupted (by way of data in socket "s"), (3) or data from your socket.

- Martin.

Note, no: error checking, thread safety, etc....

#include <apr_poll.h>
#include <apr_network_io.h>

apr_socket_t *s;
apr_sockaddr_t *sa;

extern "C" void sigint_handler(int sig) {
    char buf = 'x';
    apr_size_t len = 1;
    apr_socket_sendto(s, sa, 0, &buf, &len);
}

int main()
{
    apr_pool_t         *pool;
    apr_pollset_t      *poll_set;
    int                 rv = 0;
    const apr_pollfd_t *descs = NULL;
    apr_pollfd_t        socket_pollfd;

    /* Initialize APR */
    apr_initialize();
    apr_pool_create(&pool, NULL);
   
    /* Create a socket */
    apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 0, 0, pool);
    apr_socket_create(&s, sa->family, SOCK_DGRAM, 0, pool);
    apr_socket_bind(s, sa);

    /* Set the interrupt signal handler */
    signal(SIGINT,sigint_handler);

    /* Create a poll set and add the socket to the poll set */
    apr_pollset_create(&poll_set,1,pool,0);

    socket_pollfd.desc_type = APR_POLL_SOCKET;
    socket_pollfd.reqevents = APR_POLLIN;
    socket_pollfd.desc.s = s;
    socket_pollfd.client_data = s;

    apr_pollset_add(poll_set, &socket_pollfd);
   
    /* Sit in select() for 30 secs.  If interrupted before then,
     * socket will have data (rv == 1), otherwise rv = 0.
     */
    apr_pollset_poll(poll_set, 30000000,&rv,&descs);
   
    printf("result = %d\n",rv);

    return 0;
}


ERIC WOOD wrote:
Thanks for the response.

I was unaware apr had a select(); I thought that is what pollset() was
for.  In any case, I don't see how it would help my blocking problem. 
As I mentioned at my comments after my code:

  
This code on Windows causes a WSAEWOULDBLOCK error when no data is
received and a WSAEMSGSIZE when a datagram is received.  If I set it
    
to
  
block and specify a timeout, then I get a WSAETIMEDOUT error when no
data is received and a WSAEMSGSIZE when a datagram is received.  If
    
I
  
set it to block AND do not set a timeout, I receive the datagram
correctly, but then I can't do anything else while waiting for a
datagram (like catch the exit signal).  Any guidance you can provide
    
is
  
appreciated.
    

 If I configure non-blocking, I get Winsock errors.  If I block(), then
I don't get to sleep() til after I receive a message.  I'm looking for
an answer as to why I can't configure non-blocking.

  
Martin Schlapfer <martin@schlapfer.com> 4/3/2009 12:51 PM >>>
        
Have you tried sitting on select() rather than sleeping?
-Martin.

ERIC WOOD wrote:
  
I am having trouble receiving UDP datagrams without blocking:  Here
    
is
  
my code snippet:

  // Create the socket address
  rv = apr_sockaddr_info_get(&sa, "localhost", APR_INET, iPort, 0,
mp);
  if( rv != APR_SUCCESS )
  {
    std::cout << "Failed to get socket address for receiving
    
messages"
  
		      << std::endl; 
	return -1;
  }
   
  // Create the socket
  rv = apr_socket_create(&s, sa->family, SOCK_DGRAM, APR_PROTO_UDP,
mp);
//  rv = apr_socket_create(&s, sa->family, SOCK_STREAM,
    
APR_PROTO_TCP,
  
mp);
  if( rv != APR_SUCCESS )
  {
    std::cout << "Failed to create socket for receiving messages" <<
std::endl; 
	return -1;
  }

  // Set options
  apr_socket_opt_set( s, APR_SO_NONBLOCK, 1 );
  apr_socket_timeout_set( s, APR_USEC_PER_SEC );


  // Bind the socket.  
  rv = apr_socket_bind( s, sa );
  if( rv != APR_SUCCESS )
  {
    std::cout << "Failed to bind socket for receiving messages" <<
std::endl; 
	return -1;
  }

  finished = 0;

  char buf[1048];
  apr_size_t len = 1048;
  apr_sockaddr_t * saRecvdFrom;

  // Main loop
  std::cout << "\n\nUGCS Security Banner Client started. Enter
    
CTRL+C
  
to \
exit.\n\n" << std::endl;
  while(!finished)
  {
    // Do blocking reads with 1 sec timeout to allow for signal
catching
    apr_status_t rv = apr_socket_recvfrom(sa, s, 0, buf, &len);
	if( rv != APR_SUCCESS && rv != APR_TIMEUP )
    {
	  char sError[1048];
	  apr_strerror( rv, sError, 1048 );
	  std::cout << "Error receiving data from socket.  Error: " 
		        << sError << "(" << rv << ")" << std::endl; 
	 // return -1;
    }
	
	if ( len > 0 )
	{
	  std::cout << "Data received" << std::endl;
	}
	std::cout << "tick" << std::endl;
	sleep( 1000 );
  }

 
This code on Windows causes a WSAEWOULDBLOCK error when no data is
received and a WSAEMSGSIZE when a datagram is received.  If I set it
    
to
  
block and specify a timeout, then I get a WSAETIMEDOUT error when no
data is received and a WSAEMSGSIZE when a datagram is received.  If
    
I
  
set it to block AND do not set a timeout, I receive the datagram
correctly, but then I can't do anything else while waiting for a
datagram (like catch the exit signal).  Any guidance you can provide
    
is
  
appreciated.