Hi,
I have written some very simple test server using apr (src included).

I met a problem on Windoze NT (among other things):
When the receive timeout occures on a call apr_socket_recv() in the
serving thread, a call to apr_socket_accept() is also interrupted in the
main thread. Next accept on the same socket ends on "socket operation on
non-socket".

The code output on Windoze NT4.0 (service pack 6) follows.
I simply ran the threadsock.exe and created one connection using the
netcat (from other host) and waited for timeout.

   apr_app_initialize(): done
   apr_pool_create(): done
   apr_socket_create(): done
   apr_sockaddr_info_get(): done
   apr_socket_bind(): done
   apr_socket_listen(): done
   apr_socket_accept(): done
   apr_thread_create(): done
   apr_socket_accept(): apr_thread_detach(): done
   apr_socket_timeout_set(): done
   apr_socket_send(): done
    - sent 13 bytes
   socket recv: apr_socket_recv() failed: Connection timed out
   failed: Interrupted system call
   apr_socket_accept(): failed: Socket operation on non-socket

String "failed: Interrupted system call" belongs to preceding
"apr_socket_accept():" of course. :-)

The listening master socket is probably away. This is apr or windoze
related behavior? (On Linux i386 this works like I expected.)

Is it possible to write simple server like this (performance doesn't
matter) without need a special code for Win32?

Excuse my English, please.
Thanks
-- 
Zito
#include <stdio.h>
#include <stdlib.h>
#include <apr.h>
#include <apr_general.h>
#include <apr_network_io.h>
#include <apr_pools.h>
#include <apr_thread_proc.h>
#include <apr_time.h>

#define ASSERT_APR_SUCCESS(heading, op)		\
    {						\
	apr_status_t	rv;			\
	fprintf(stderr, heading ": ");		\
	if ( (rv = op) != APR_SUCCESS )		\
	{					\
	    char    buf[128];			\
	    fprintf(stderr, "failed: %s\n",	\
		    apr_strerror(rv, buf, sizeof(buf)));    \
	    exit(1);				\
	}					\
	fprintf(stderr, "done\n");		\
    }


static void * APR_THREAD_FUNC thread_serv_start(apr_thread_t *thd, void *data);

int main(int argc, char const * const argv[])
{
    apr_status_t    rv;
    apr_pool_t	    *pglobal;
    apr_socket_t    *sd, *sd2;
    apr_sockaddr_t  *sa;
    apr_thread_t    *child;

    ASSERT_APR_SUCCESS("apr_app_initialize()",
	    apr_app_initialize(&argc, &argv, NULL));

    atexit(&apr_terminate);

    ASSERT_APR_SUCCESS("apr_pool_create()",
	    apr_pool_create(&pglobal, NULL));

    ASSERT_APR_SUCCESS("apr_socket_create()",
	    apr_socket_create(&sd, APR_INET, SOCK_STREAM, pglobal));

    ASSERT_APR_SUCCESS("apr_sockaddr_info_get()",
	    apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_INET, 12345,
		0, pglobal));

    ASSERT_APR_SUCCESS("apr_socket_bind()",
	    apr_socket_bind(sd, sa));

    ASSERT_APR_SUCCESS("apr_socket_listen()",
	    apr_socket_listen(sd, 1));

    while ( 1 )
    {
	fprintf(stderr, "apr_socket_accept(): ");
	if ( (rv = apr_socket_accept(&sd2, sd, pglobal)) != APR_SUCCESS )
	{
	    char    buf[128];
	    fprintf(stderr, "failed: %s\n",
		    apr_strerror(rv, buf, sizeof(buf)));
	    if ( APR_STATUS_IS_EINTR(rv) )
		continue;
	    exit(1);
	}
	fprintf(stderr, "done\n");

	ASSERT_APR_SUCCESS("apr_thread_create()",
		apr_thread_create(&child, NULL,
		    thread_serv_start, sd2, pglobal));
    }

    ASSERT_APR_SUCCESS("apr_socket_close()",
	    apr_socket_close(sd));

    fprintf(stderr, "apr_pool_destroy(): ");
    apr_pool_destroy(pglobal);
    fprintf(stderr, "done\n");

    return 0;
}



static void * APR_THREAD_FUNC thread_serv_start(apr_thread_t *thd, void *data)
{
    apr_socket_t    *sd2 = (apr_socket_t *)data;
    apr_status_t    rv;
    apr_size_t	    n;
    char	    buf[256];

    apr_sleep(10000);				/* glibc bug workaround */
    ASSERT_APR_SUCCESS("apr_thread_detach()",
	    apr_thread_detach(thd));

    ASSERT_APR_SUCCESS("apr_socket_timeout_set()",
	    apr_socket_timeout_set(sd2, 10000000L));

#define HELLO_STR   "Hello world!\n"
    n = strlen(HELLO_STR);
    ASSERT_APR_SUCCESS("apr_socket_send()",
	    apr_socket_send(sd2, HELLO_STR, &n));
    fprintf(stderr, " - sent %d bytes\n", n);

//    ASSERT_APR_SUCCESS("apr_socket_shutdown()",
//	    apr_socket_shutdown(sd2, APR_SHUTDOWN_WRITE));

    fprintf(stderr, "socket recv: ");
    n = sizeof(buf);
    if ( (rv = apr_socket_recv(sd2, buf, &n)) != APR_SUCCESS
	    && rv != APR_EOF )
    {
	fprintf(stderr, "apr_socket_recv() failed: %s\n",
		apr_strerror(rv, buf, sizeof(buf)));
	if ( ! APR_STATUS_IS_TIMEUP(rv) )
	    exit(1);
    }
    else
    {
	fprintf(stderr, "done\n");
	fprintf(stderr, " - read %d bytes\n", n);
	fwrite(buf, n, 1, stderr);
    }

    ASSERT_APR_SUCCESS("apr_socket_close()",
	    apr_socket_close(sd2));

    apr_thread_exit(thd, APR_SUCCESS);
    return NULL;
}

Reply via email to