gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r36870 - in libmicrohttpd: . src/microhttpd


From: gnunet
Subject: [GNUnet-SVN] r36870 - in libmicrohttpd: . src/microhttpd
Date: Mon, 25 Jan 2016 15:17:44 +0100

Author: Karlson2k
Date: 2016-01-25 15:17:43 +0100 (Mon, 25 Jan 2016)
New Revision: 36870

Added:
   libmicrohttpd/src/microhttpd/test_shutdown_select.c
Modified:
   libmicrohttpd/ChangeLog
   libmicrohttpd/configure.ac
   libmicrohttpd/src/microhttpd/Makefile.am
Log:
Added test for checking ability of shutdown() on socket to trigger select()

Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog     2016-01-24 18:36:59 UTC (rev 36869)
+++ libmicrohttpd/ChangeLog     2016-01-25 14:17:43 UTC (rev 36870)
@@ -1,3 +1,7 @@
+Mon Jan 25 13:45:50 CET 2016
+       Added check test for triggering select() on
+       listen socket. -EG
+
 Thu Jan 21 19:35:18 CET 2016
        Fixed old bug with making sockets non-blocking on
        various platforms so now sockets are really

Modified: libmicrohttpd/configure.ac
===================================================================
--- libmicrohttpd/configure.ac  2016-01-24 18:36:59 UTC (rev 36869)
+++ libmicrohttpd/configure.ac  2016-01-25 14:17:43 UTC (rev 36870)
@@ -141,6 +141,7 @@
 CFLAGS="$save_CFLAGS"
 
 # Check system type
+shutdown_trig_select='no'
 AC_MSG_CHECKING([[for target host OS]])
 case "$host_os" in
 *darwin* | *rhapsody* | *macosx*)
@@ -177,7 +178,7 @@
      ;;
 *arm-linux*)
      AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux kernel])
-     AC_DEFINE_UNQUOTED(HAVE_LISTEN_SHUTDOWN,1,[can use shutdown on listen 
sockets])
+     shutdown_trig_select='yes'
      mhd_host_os='ARM Linux'
      AC_MSG_RESULT([[$mhd_host_os]])
      CFLAGS="-fPIC -pipe $CFLAGS"
@@ -184,7 +185,7 @@
      ;;
 *linux*)
      AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux kernel])
-     AC_DEFINE_UNQUOTED(HAVE_LISTEN_SHUTDOWN,1,[can use shutdown on listen 
sockets])
+     shutdown_trig_select='yes'
      mhd_host_os='Linux'
      AC_MSG_RESULT([[$mhd_host_os]])
      ;;
@@ -233,6 +234,9 @@
 ;;
 esac
 
+AM_CONDITIONAL([HAVE_LISTEN_SHUTDOWN], [test "x$shutdown_trig_select" = 
"xyes"])
+AS_IF([test "x$shutdown_trig_select" = "xyes"], 
[AC_DEFINE([HAVE_LISTEN_SHUTDOWN],[1],[can use shutdown on listen sockets])])
+
 AC_ARG_WITH([threads],
    [AS_HELP_STRING([--with-threads=LIB],[choose threading library (posix, w32, 
auto) [auto]])],
    [], [with_threads='auto'])

Modified: libmicrohttpd/src/microhttpd/Makefile.am
===================================================================
--- libmicrohttpd/src/microhttpd/Makefile.am    2016-01-24 18:36:59 UTC (rev 
36869)
+++ libmicrohttpd/src/microhttpd/Makefile.am    2016-01-25 14:17:43 UTC (rev 
36870)
@@ -140,6 +140,7 @@
 
 
 check_PROGRAMS = \
+  test_shutdown_select \
   test_daemon
 
 if HAVE_POSTPROCESSOR
@@ -151,6 +152,11 @@
 
 TESTS = $(check_PROGRAMS)
 
+if !HAVE_LISTEN_SHUTDOWN
+XFAIL_TESTS = \
+  test_shutdown_select
+endif
+
 test_daemon_SOURCES = \
   test_daemon.c
 test_daemon_LDADD = \
@@ -178,3 +184,12 @@
 test_postprocessor_large_LDADD = \
   $(top_builddir)/src/microhttpd/libmicrohttpd.la \
   $(MHD_W32_LIB)
+
+test_shutdown_select_SOURCES = \
+  test_shutdown_select.c
+if USE_POSIX_THREADS
+test_shutdown_select_CFLAGS = \
+  $(AM_CFLAGS) $(PTHREAD_CFLAGS)
+test_shutdown_select_LDADD = \
+  $(PTHREAD_LIBS)
+endif

Added: libmicrohttpd/src/microhttpd/test_shutdown_select.c
===================================================================
--- libmicrohttpd/src/microhttpd/test_shutdown_select.c                         
(rev 0)
+++ libmicrohttpd/src/microhttpd/test_shutdown_select.c 2016-01-25 14:17:43 UTC 
(rev 36870)
@@ -0,0 +1,299 @@
+/*
+     This file is part of libmicrohttpd
+     Copyright (C) 2016 Karlson2k (Evgeny Grin)
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file microhttpd/test_shutdown_select.c
+ * @brief  Test whether shutdown socket triggers select
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "MHD_config.h"
+#include "platform_interface.h"
+#include "platform.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif /* HAVE_TIME_H */
+
+#if defined(MHD_USE_POSIX_THREADS)
+#include <pthread.h>
+#endif /* MHD_USE_POSIX_THREADS */
+
+#if defined(MHD_WINSOCK_SOCKETS)
+#include <winsock2.h>
+#include <windows.h>
+#define sock_errno (WSAGetLastError())
+#elif defined(MHD_POSIX_SOCKETS)
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif /* HAVE_ARPA_INET_H */
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#define sock_errno (errno)
+#endif /* MHD_POSIX_SOCKETS */
+
+#ifndef SOMAXCONN
+#define SOMAXCONN 511
+#endif /* ! SOMAXCONN */
+
+#if !defined(SHUT_RDWR) && defined(SD_BOTH)
+#define SHUT_RDWR SD_BOTH
+#endif
+
+
+static MHD_socket
+start_socket_listen(int domain)
+{
+/* Create sockets similarly to daemon.c */
+  MHD_socket fd;
+  int cloexec_set;
+  struct sockaddr_in sock_addr;
+  socklen_t addrlen;
+
+#ifdef MHD_WINSOCK_SOCKETS
+  unsigned long flags = 1;
+#else  /* MHD_POSIX_SOCKETS */
+  int flags;
+#endif /* MHD_POSIX_SOCKETS */
+
+#if defined(MHD_POSIX_SOCKETS) && defined(SOCK_CLOEXEC)
+  fd = socket (domain, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  cloexec_set = 1;
+#elif defined(MHD_WINSOCK_SOCKETS) && defined (WSA_FLAG_NO_HANDLE_INHERIT)
+  fd = WSASocketW (domain, SOCK_STREAM, 0, NULL, 0, 
WSA_FLAG_NO_HANDLE_INHERIT);
+  cloexec_set = 1;
+#else  /* !SOCK_CLOEXEC */
+  fd = socket (domain, SOCK_STREAM, 0);
+  cloexec_set = 0;
+#endif /* !SOCK_CLOEXEC */
+  if ( (MHD_INVALID_SOCKET == fd) && (cloexec_set) )
+    {
+      fd = socket (domain, SOCK_STREAM, 0);
+      cloexec_set = 0;
+    }
+  if (MHD_INVALID_SOCKET == fd)
+    {
+      fprintf (stderr, "Can't create socket: %u\n",
+               (unsigned)sock_errno);
+      return MHD_INVALID_SOCKET;
+    }
+
+  if (!cloexec_set)
+    {
+#ifdef MHD_WINSOCK_SOCKETS
+    if (!SetHandleInformation ((HANDLE)fd, HANDLE_FLAG_INHERIT, 0))
+      fprintf (stderr, "Failed to make socket non-inheritable: %u\n",
+               (unsigned int)GetLastError ());
+#else  /* MHD_POSIX_SOCKETS */
+    flags = fcntl (fd, F_GETFD);
+    if ( ( (-1 == flags) ||
+           ( (flags != (flags | FD_CLOEXEC)) &&
+             (0 != fcntl (fd, F_SETFD, flags | FD_CLOEXEC)) ) ) )
+      fprintf (stderr, "Failed to make socket non-inheritable: %s\n",
+               MHD_socket_last_strerr_ ());
+#endif /* MHD_POSIX_SOCKETS */
+    }
+
+  memset (&sock_addr, 0, sizeof (struct sockaddr_in));
+  sock_addr.sin_family = AF_INET;
+  sock_addr.sin_port = htons (0);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sock_addr.sin_len = sizeof (struct sockaddr_in);
+#endif
+  addrlen = sizeof (struct sockaddr_in);
+
+  if (bind (fd, (const struct sockaddr*) &sock_addr, addrlen) < 0)
+    {
+      fprintf (stderr, "Failed to bind socket: %u\n",
+               (unsigned)sock_errno);
+      MHD_socket_close_ (fd);
+      return MHD_INVALID_SOCKET;
+    }
+
+#ifdef MHD_WINSOCK_SOCKETS
+  if (0 != ioctlsocket (fd, FIONBIO, &flags))
+    {
+      fprintf (stderr, "Failed to make socket non-blocking: %u\n",
+               (unsigned)sock_errno);
+      MHD_socket_close_ (fd);
+      return MHD_INVALID_SOCKET;
+    }
+#else  /* MHD_POSIX_SOCKETS */
+  flags = fcntl (fd, F_GETFL);
+  if ( ( (-1 == flags) ||
+         ( (flags != (flags | O_NONBLOCK)) &&
+           (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) ) ) )
+    {
+      fprintf (stderr, "Failed to make socket non-blocking: %s\n",
+              MHD_socket_last_strerr_ ());
+      MHD_socket_close_ (fd);
+      return MHD_INVALID_SOCKET;
+    }
+#endif /* MHD_POSIX_SOCKETS */
+
+  if (listen(fd, SOMAXCONN) < 0)
+    {
+      fprintf (stderr, "Failed to listen on socket: %u\n",
+               (unsigned)sock_errno);
+      MHD_socket_close_ (fd);
+      return MHD_INVALID_SOCKET;
+    }
+
+  return fd;
+}
+
+
+MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
+select_thread(void* data)
+{
+  /* use select() like in daemon.c */
+  MHD_socket listen_sock = *((MHD_socket*)data);
+  fd_set rs, ws;
+  struct timeval timeout;
+
+  FD_ZERO(&rs);
+  FD_ZERO(&ws);
+  FD_SET(listen_sock, &rs);
+  timeout.tv_usec = 0;
+  timeout.tv_sec = 7;
+
+  MHD_SYS_select_(listen_sock + 1, &rs, &ws, NULL, &timeout);
+
+  return (MHD_THRD_RTRN_TYPE_)0;
+}
+
+
+static void
+local_sleep(unsigned seconds)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  Sleep(seconds * 1000);
+#else
+  unsigned seconds_left = seconds;
+  do
+    {
+      seconds_left = sleep(seconds_left);
+    } while (seconds_left > 0);
+#endif
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+  int i;
+  time_t start_t, end_t;
+  int result = 0;
+
+#ifdef MHD_WINSOCK_SOCKETS
+  WORD ver_req;
+  WSADATA wsa_data;
+  int err;
+  ver_req = MAKEWORD(2, 2);
+
+  err = WSAStartup(ver_req, &wsa_data);
+  if (err != 0 || MAKEWORD(2, 2) != wsa_data.wVersion)
+    {
+      printf("WSAStartup() failed\n");
+      WSACleanup();
+      return 99;
+    }
+#endif /* MHD_WINSOCK_SOCKETS */
+
+  /* try several times to ensure that accidental incoming connection
+   * didn't interfere with test results
+   */
+  for (i = 0; i < 5 && result == 0; i++)
+    {
+      MHD_thread_handle_ sel_thrd;
+       /* fprint f(stdout, "Creating, binding and listening socket...\n"); */
+      MHD_socket listen_socket = start_socket_listen (AF_INET);
+      if (MHD_INVALID_SOCKET == listen_socket)
+        return 99;
+
+      /* fprintf (stdout, "Starting select() thread...\n"); */
+#if defined(MHD_USE_POSIX_THREADS)
+      if (0 != pthread_create (&sel_thrd, NULL, &select_thread, 
&listen_socket))
+        {
+          MHD_socket_close_ (listen_socket);
+          fprintf (stderr, "Can't start thread\n");
+          return 99;
+        }
+#elif defined(MHD_USE_W32_THREADS)
+      sel_thrd = (HANDLE)_beginthreadex (NULL, 0, &select_thread, 
&listen_socket, 0, NULL);
+      if (0 == (sel_thrd))
+        {
+          MHD_socket_close_ (listen_socket);
+          fprintf (stderr, "Can't start select() thread\n");
+          return 99;
+        }
+#else
+#error No threading lib available
+#endif
+      /* fprintf (stdout, "Waiting...\n"); */
+      local_sleep(1); /* make sure that select() is started */
+
+      /* fprintf (stdout, "Shutting down socket...\n"); */
+      start_t = time (NULL);
+      shutdown (listen_socket, SHUT_RDWR);
+
+      /* fprintf (stdout, "Waiting for thread to finish...\n"); */
+      if (0 != MHD_join_thread_(sel_thrd))
+        {
+          MHD_socket_close_(listen_socket);
+          fprintf (stderr, "Can't join select() thread\n");
+          return 99;
+        }
+      end_t = time (NULL);
+      /* fprintf (stdout, "Thread finished.\n"); */
+      MHD_socket_close_(listen_socket);
+
+      if (start_t == (time_t)-1 || end_t == (time_t)-1)
+        {
+          MHD_socket_close_(listen_socket);
+          fprintf (stderr, "Can't get current time\n");
+          return 99;
+        }
+      if (end_t - start_t > 3)
+        result++;
+    }
+
+#ifdef MHD_WINSOCK_SOCKETS
+  WSACleanup();
+#endif /* MHD_WINSOCK_SOCKETS */
+
+  return result;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]