From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Lars Ingebrigtsen Newsgroups: gmane.emacs.bugs Subject: bug#32452: 26.1; gnutls_try_handshake maxes out cpu retrying when server is a bit busy Date: Wed, 02 Mar 2022 02:43:40 +0100 Message-ID: <87tuchjfhv.fsf__19802.0992496581$1646185481$gmane$org@gnus.org> References: <87wosqwlu3.fsf@gmail.com> <87k0doi6vy.fsf@gnus.org> <905557ed-58f6-8671-51de-a44e73029aa9@cs.ucla.edu> <87ley15pp6.fsf@gnus.org> <172175b8-c6b3-314f-e803-e00d04f5d57a@cs.ucla.edu> <87y221436n.fsf@gnus.org> <0df255b3-41a1-619d-97d3-28fd246e0b9f@cs.ucla.edu> <87pmnc4p64.fsf@gnus.org> <87v8x3znmm.fsf@gnus.org> <6f364184-7fa8-04f3-44a9-22ce40b872e8@cs.ucla.edu> <8735k5vezs.fsf@gnus.org> <83ee3pprkr.fsf@gnu.org> <87pmn9txzo.fsf@gnus.org> <87ee3ns6x0.fsf@gnus.org> <78c5037a-ac96-e7be-532f-b1776ed25b2b@cs.ucla.edu> <87a6e9n0rg.fsf@gnus.org> <87czj5ld38.fsf@gnus.org> <87y21tjggy.fsf__43924.9896955275$1646184230$gmane$org@gnus.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="3078"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: 32452@debbugs.gnu.org, bug-gnulib@gnu.org, npostavs@gmail.com To: Paul Eggert Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Mar 02 02:44:34 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nPE2a-0000bw-Rk for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 02 Mar 2022 02:44:33 +0100 Original-Received: from localhost ([::1]:33030 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nPE2Z-00036i-JD for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 01 Mar 2022 20:44:31 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:55536) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nPE29-00034N-7f for bug-gnu-emacs@gnu.org; Tue, 01 Mar 2022 20:44:06 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:44775) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nPE26-0007tw-En for bug-gnu-emacs@gnu.org; Tue, 01 Mar 2022 20:44:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nPE26-0008Ut-62 for bug-gnu-emacs@gnu.org; Tue, 01 Mar 2022 20:44:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Lars Ingebrigtsen Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 02 Mar 2022 01:44:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 32452 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: moreinfo Original-Received: via spool by 32452-submit@debbugs.gnu.org id=B32452.164618543632640 (code B ref 32452); Wed, 02 Mar 2022 01:44:02 +0000 Original-Received: (at 32452) by debbugs.gnu.org; 2 Mar 2022 01:43:56 +0000 Original-Received: from localhost ([127.0.0.1]:38672 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nPE1z-0008UN-U7 for submit@debbugs.gnu.org; Tue, 01 Mar 2022 20:43:56 -0500 Original-Received: from quimby.gnus.org ([95.216.78.240]:54266) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nPE1x-0008U9-OJ for 32452@debbugs.gnu.org; Tue, 01 Mar 2022 20:43:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=PO1GUIG8RdZdu7z0RJVQSTMUoooBzeGItERqHnLhM98=; b=B8ZR+wKyViOHJAlE8S3LtXbrS/ 6GrbtHm8RDEBmmBxpyjMoMG8fYnkZHbUMfwq1rer574trWASrE2PBdQWesIZvzuKH9nEIdkR1eySY KNZWWPD21eYF3Oglzc017sCXqeIVpBNpHVP0vjrQf0PrsNdzZkMj0jcFi9ErtD1xdhD8=; Original-Received: from [84.212.220.105] (helo=giant) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nPE1l-0005Dg-Hr; Wed, 02 Mar 2022 02:43:44 +0100 Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAABGdBTUEAALGPC/xhBQAAACBj SFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAD1BMVEUUExFVVUuKh3HR 08f///8lsDxHAAAAAWJLR0QEj2jZUQAAAAd0SU1FB+YDAgErDJ9kOxEAAAGxSURBVDjLvVNRruMw CDTOBcC+gA0XiOH+d9vBSdP2vZ+VVlpLSVpjZgYGl/K/FuORQowX/30WWYTP3/st9vKfUN1JrFRk fUeOOAG2E/0LP2J/hEvPI2+gBKDWJhOrfgRi5Xm1mHlgfDBkgdBlK6nbOyGZJ5m7Co7XV0oFg9Co Ldaxxb3KPLxQihQbhWm0B8vOUpNV7aRSWbneRQKptZH0Zzba+Cah1JriBcw4W7mviwIaK9dWZJY5 IWO2K2C+SueujPrQKT3cd4/RJy8hodHDLUocKHTsTqhKCB5d2pZow8aWFR4hFhxLY/RYPa5ewyPV CoMMW8V0dreLvBpcWAJ15hVnybtcboPKMuCJJEJul/MUpwKWATfg+QJUjCuwPAPQzX0H6A5MNART 2EVeBl0/qksbNKsOEWHCS9bdXXSJUNfMFEJuOx8/WkG5k2+H+ngclNLU1NvlUH97LnM2zMI1jY/n GKtpC0MC5nS1PrOIeid4JS8OhPdnrlHils65I7TeI4oebFxIpUfTRe+6/ybDR8Ie98k37PfNMW87 0nSU75WGZvd/7r9u5+/9FDql/MP6A2XpOvY/2Y80AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIyLTAz LTAyVDAxOjQzOjEyKzAwOjAw23cMCwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMi0wMy0wMlQwMTo0 MzoxMiswMDowMKoqtLcAAAAASUVORK5CYII= X-Now-Playing: Fever's _Too Bad But True_: "Rubber Cell" In-Reply-To: <87y21tjggy.fsf__43924.9896955275$1646184230$gmane$org@gnus.org> (Lars Ingebrigtsen's message of "Wed, 02 Mar 2022 02:22:37 +0100") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:227901 Archived-At: Lars Ingebrigtsen writes: > diff --git a/admin/merge-gnulib b/admin/merge-gnulib > index fec469c017..ea3d23686f 100755 That wasn't the complete diff. Here it is: diff --git a/admin/merge-gnulib b/admin/merge-gnulib index fec469c017..ea3d23686f 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -40,7 +40,7 @@ GNULIB_MODULES= getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog ieee754-h ignore-value intprops largefile libgmp lstat manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime - nproc nstrftime + nanosleep nproc nstrftime pathmax pipe2 pselect pthread_sigmask qcopy-acl readlink readlinkat regex sig2str sigdescr_np socklen stat-time std-gnu11 stdalign stddef stdio diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 3a9f5b9818..b79eebc804 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -129,6 +129,7 @@ # minmax \ # mkostemp \ # mktime \ +# nanosleep \ # nproc \ # nstrftime \ # pathmax \ @@ -2497,6 +2498,16 @@ EXTRA_libgnu_a_SOURCES += mktime.c endif ## end gnulib module mktime-internal +## begin gnulib module nanosleep +ifeq (,$(OMIT_GNULIB_MODULE_nanosleep)) + +ifneq (,$(GL_COND_OBJ_NANOSLEEP_CONDITION)) +libgnu_a_SOURCES += nanosleep.c +endif + +endif +## end gnulib module nanosleep + ## begin gnulib module nproc ifeq (,$(OMIT_GNULIB_MODULE_nproc)) diff --git a/lib/nanosleep.c b/lib/nanosleep.c new file mode 100644 index 0000000000..446794edc0 --- /dev/null +++ b/lib/nanosleep.c @@ -0,0 +1,195 @@ +/* Provide a replacement for the POSIX nanosleep function. + + Copyright (C) 1999-2000, 2002, 2004-2022 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering + and Bruno Haible for the native Windows part */ + +#include + +#include + +#include "intprops.h" +#include "verify.h" + +#include +#include +#include +#include +#include + +#include + +#include + + +enum { BILLION = 1000 * 1000 * 1000 }; + +#if HAVE_BUG_BIG_NANOSLEEP + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +# undef nanosleep +{ + /* nanosleep mishandles large sleeps due to internal overflow problems. + The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which + can't sleep more than 24.85 days (2^31 milliseconds). Similarly, + cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds). + Solve this by breaking the sleep up into smaller chunks. */ + + if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) + { + errno = EINVAL; + return -1; + } + + { + /* Verify that time_t is large enough. */ + verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60); + const time_t limit = 24 * 24 * 60 * 60; + time_t seconds = requested_delay->tv_sec; + struct timespec intermediate; + intermediate.tv_nsec = requested_delay->tv_nsec; + + while (limit < seconds) + { + int result; + intermediate.tv_sec = limit; + result = nanosleep (&intermediate, remaining_delay); + seconds -= limit; + if (result) + { + if (remaining_delay) + remaining_delay->tv_sec += seconds; + return result; + } + intermediate.tv_nsec = 0; + } + intermediate.tv_sec = seconds; + return nanosleep (&intermediate, remaining_delay); + } +} + +#elif defined _WIN32 && ! defined __CYGWIN__ +/* Native Windows platforms. */ + +# define WIN32_LEAN_AND_MEAN +# include + +/* The Windows API function Sleep() has a resolution of about 15 ms and takes + at least 5 ms to execute. We use this function for longer time periods. + Additionally, we use busy-looping over short time periods, to get a + resolution of about 0.01 ms. In order to measure such short timespans, + we use the QueryPerformanceCounter() function. */ + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +{ + static bool initialized; + /* Number of performance counter increments per nanosecond, + or zero if it could not be determined. */ + static double ticks_per_nanosecond; + + if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) + { + errno = EINVAL; + return -1; + } + + /* For requested delays of one second or more, 15ms resolution is + sufficient. */ + if (requested_delay->tv_sec == 0) + { + if (!initialized) + { + /* Initialize ticks_per_nanosecond. */ + LARGE_INTEGER ticks_per_second; + + if (QueryPerformanceFrequency (&ticks_per_second)) + ticks_per_nanosecond = + (double) ticks_per_second.QuadPart / 1000000000.0; + + initialized = true; + } + if (ticks_per_nanosecond) + { + /* QueryPerformanceFrequency worked. We can use + QueryPerformanceCounter. Use a combination of Sleep and + busy-looping. */ + /* Number of milliseconds to pass to the Sleep function. + Since Sleep can take up to 8 ms less or 8 ms more than requested + (or maybe more if the system is loaded), we subtract 10 ms. */ + int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10; + /* Determine how many ticks to delay. */ + LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond; + /* Start. */ + LARGE_INTEGER counter_before; + if (QueryPerformanceCounter (&counter_before)) + { + /* Wait until the performance counter has reached this value. + We don't need to worry about overflow, because the performance + counter is reset at reboot, and with a frequency of 3.6E6 + ticks per second 63 bits suffice for over 80000 years. */ + LONGLONG wait_until = counter_before.QuadPart + wait_ticks; + /* Use Sleep for the longest part. */ + if (sleep_millis > 0) + Sleep (sleep_millis); + /* Busy-loop for the rest. */ + for (;;) + { + LARGE_INTEGER counter_after; + if (!QueryPerformanceCounter (&counter_after)) + /* QueryPerformanceCounter failed, but succeeded earlier. + Should not happen. */ + break; + if (counter_after.QuadPart >= wait_until) + /* The requested time has elapsed. */ + break; + } + goto done; + } + } + } + /* Implementation for long delays and as fallback. */ + Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000); + + done: + /* Sleep is not interruptible. So there is no remaining delay. */ + if (remaining_delay != NULL) + { + remaining_delay->tv_sec = 0; + remaining_delay->tv_nsec = 0; + } + return 0; +} + +#else +/* Other platforms lacking nanosleep. + It's not clear whether these are still practical porting targets. + For now, just fall back on pselect. */ + +/* Suspend execution for at least *REQUESTED_DELAY seconds. The + *REMAINING_DELAY part isn't implemented yet. */ + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +{ + return pselect (0, NULL, NULL, NULL, requested_delay, NULL); +} +#endif diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 1d31239d2d..fb5f1b52a4 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -140,6 +140,7 @@ AC_DEFUN # Code from module mktime: # Code from module mktime-internal: # Code from module multiarch: + # Code from module nanosleep: # Code from module nocrash: # Code from module nproc: # Code from module nstrftime: @@ -430,6 +431,10 @@ AC_DEFUN fi gl_TIME_MODULE_INDICATOR([mktime]) gl_MULTIARCH + gl_FUNC_NANOSLEEP + gl_CONDITIONAL([GL_COND_OBJ_NANOSLEEP], + [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]) + gl_TIME_MODULE_INDICATOR([nanosleep]) gl_NPROC gl_FUNC_GNU_STRFTIME gl_PATHMAX @@ -1304,6 +1309,7 @@ AC_DEFUN lib/mkostemp.c lib/mktime-internal.h lib/mktime.c + lib/nanosleep.c lib/nproc.c lib/nproc.h lib/nstrftime.c @@ -1456,6 +1462,7 @@ AC_DEFUN m4/mktime.m4 m4/mode_t.m4 m4/multiarch.m4 + m4/nanosleep.m4 m4/nocrash.m4 m4/nproc.m4 m4/nstrftime.m4 diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4 new file mode 100644 index 0000000000..1964b1ea47 --- /dev/null +++ b/m4/nanosleep.m4 @@ -0,0 +1,139 @@ +# serial 41 + +dnl From Jim Meyering. +dnl Check for the nanosleep function. +dnl If not found, use the supplied replacement. +dnl + +# Copyright (C) 1999-2001, 2003-2022 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_NANOSLEEP], +[ + AC_REQUIRE([gl_TIME_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Persuade glibc and Solaris to declare nanosleep. + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_DECLS_ONCE([alarm]) + + nanosleep_save_libs=$LIBS + + # Solaris 2.5.1 needs -lposix4 to get the nanosleep function. + # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4. + LIB_NANOSLEEP= + AC_SUBST([LIB_NANOSLEEP]) + AC_SEARCH_LIBS([nanosleep], [rt posix4], + [test "$ac_cv_search_nanosleep" = "none required" || + LIB_NANOSLEEP=$ac_cv_search_nanosleep]) + if test "x$ac_cv_search_nanosleep" != xno; then + dnl The system has a nanosleep function. + + AC_REQUIRE([gl_MULTIARCH]) + if test $APPLE_UNIVERSAL_BUILD = 1; then + # A universal build on Apple Mac OS X platforms. + # The test result would be 'no (mishandles large arguments)' in 64-bit + # mode but 'yes' in 32-bit mode. But we need a configuration result that + # is valid in both modes. + gl_cv_func_nanosleep='no (mishandles large arguments)' + fi + + AC_CACHE_CHECK([for working nanosleep], + [gl_cv_func_nanosleep], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + #include + #include + #include + #include + #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + #define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) + + #if HAVE_DECL_ALARM + static void + check_for_SIGALRM (int sig) + { + if (sig != SIGALRM) + _exit (1); + } + #endif + + int + main () + { + static struct timespec ts_sleep; + static struct timespec ts_remaining; + /* Test for major problems first. */ + if (! nanosleep) + return 2; + ts_sleep.tv_sec = 0; + ts_sleep.tv_nsec = 1; + #if HAVE_DECL_ALARM + { + static struct sigaction act; + act.sa_handler = check_for_SIGALRM; + sigemptyset (&act.sa_mask); + sigaction (SIGALRM, &act, NULL); + alarm (1); + if (nanosleep (&ts_sleep, NULL) != 0) + return 3; + /* Test for a minor problem: the handling of large arguments. */ + ts_sleep.tv_sec = TYPE_MAXIMUM (time_t); + ts_sleep.tv_nsec = 999999999; + alarm (1); + if (nanosleep (&ts_sleep, &ts_remaining) != -1) + return 4; + if (errno != EINTR) + return 5; + if (ts_remaining.tv_sec <= TYPE_MAXIMUM (time_t) - 10) + return 6; + } + #else /* A simpler test for native Windows. */ + if (nanosleep (&ts_sleep, &ts_remaining) < 0) + return 3; + #endif + return 0; + }]])], + [gl_cv_func_nanosleep=yes], + [case $? in dnl ( + 4|5|6) gl_cv_func_nanosleep='no (mishandles large arguments)';; dnl ( + *) gl_cv_func_nanosleep=no;; + esac], + [case "$host_os" in dnl (( + linux*) # Guess it halfway works when the kernel is Linux. + gl_cv_func_nanosleep='guessing no (mishandles large arguments)' ;; + mingw*) # Guess no on native Windows. + gl_cv_func_nanosleep='guessing no' ;; + *) # If we don't know, obey --enable-cross-guesses. + gl_cv_func_nanosleep="$gl_cross_guess_normal" ;; + esac + ]) + ]) + case "$gl_cv_func_nanosleep" in + *yes) + REPLACE_NANOSLEEP=0 + ;; + *) + REPLACE_NANOSLEEP=1 + case "$gl_cv_func_nanosleep" in + *"mishandles large arguments"*) + AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], [1], + [Define to 1 if nanosleep mishandles large arguments.]) + ;; + esac + ;; + esac + else + HAVE_NANOSLEEP=0 + fi + LIBS=$nanosleep_save_libs +]) diff --git a/src/gnutls.c b/src/gnutls.c index 3ec3837067..5389b15b1e 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -616,6 +616,7 @@ gnutls_try_handshake (struct Lisp_Process *proc) gnutls_session_t state = proc->gnutls_state; int ret; bool non_blocking = proc->is_non_blocking_client; + struct timespec delay = { 0, 1000 * 1000 * 10 }; if (proc->gnutls_complete_negotiation_p) non_blocking = false; @@ -630,6 +631,7 @@ gnutls_try_handshake (struct Lisp_Process *proc) maybe_quit (); if (non_blocking && ret != GNUTLS_E_INTERRUPTED) break; + nanosleep (&delay, NULL); } proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED; -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no