]> Pileus Git - ~andy/fetchmail/commitdiff
Wrap getaddrinfo() and block SIGALRM where needed.
authorMatthias Andree <matthias.andree@gmx.de>
Mon, 14 Aug 2006 01:28:47 +0000 (01:28 -0000)
committerMatthias Andree <matthias.andree@gmx.de>
Mon, 14 Aug 2006 01:28:47 +0000 (01:28 -0000)
Also wrap freeaddrinfo() without added functionality.

svn path=/branches/BRANCH_6-3/; revision=4895

Makefile.am
NEWS
checkalias.c
configure.ac
driver.c
env.c
fetchmail.h
fm_getaddrinfo.c [new file with mode: 0644]
servport.c
socket.c

index c866488c3d292e25169459b8f7eecd873c3e7a60..db06fee0ad3a52f64667887769d9ff8f20d89f98 100644 (file)
@@ -39,7 +39,7 @@ libfm_a_SOURCES=      xmalloc.c base64.c rfc822.c report.c rfc2047e.c \
                        servport.c ntlm.h smbbyteorder.h smbdes.h smbmd4.h \
                        smbencrypt.h smbdes.c smbencrypt.c smbmd4.c smbutil.c \
                        libesmtp/gethostbyname.h libesmtp/gethostbyname.c \
-                       smbtypes.h
+                       smbtypes.h fm_getaddrinfo.c
 libfm_a_LIBADD=                $(EXTRAOBJ)
 libfm_a_DEPENDENCIES=  $(EXTRAOBJ)
 LDADD  =               libfm.a @LIBINTL@ $(LIBOBJS)
diff --git a/NEWS b/NEWS
index 6d8f922a9b3ba0a338bb2f93e398527635d55756..48d6fc4010e22ac088c974dab8b7d5d6311e04f3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -98,8 +98,9 @@ fetchmail 6.3.5 (not yet released):
   with new polls, and SIGHUP would be ignored for root users. SIGHUP now matches
   documented behavior. SIGUSR1 has always been a wakeup signal for both root
   (undocumented) and non-root users. See also the deprecation warning above.
-* Track getaddrinfo() results to properly free them after timeouts,
-  reported by Uli Zappe.  This MIGHT fix Debian Bug#294547 and Bug#377135.
+* Track getaddrinfo() results to properly free them after timeouts and make sure
+  that getaddrinfo() isn't interrupted by a timeout (which breaks on MacOS X),
+  reported by Uli Zappe.  This should fix Debian Bug#294547 and Bug#377135.
 * --logfile is now handled more carefully, errors opening the logfile are
   now reported to the TTY where fetchmail was started from.
 * fetchmail now complains and aborts when it cannot properly daemonize itself.
index 1f0495b9b3d8aea8830ab9fae01ef55476355ea7..80356ed292a5f6dca37d3e94d14f7c1e8d3d9444 100644 (file)
@@ -36,7 +36,7 @@ static int getaddresses(struct addrinfo **result, const char *name)
     hints.ai_socktype=SOCK_STREAM;
     hints.ai_protocol=PF_UNSPEC;
     hints.ai_family=AF_UNSPEC;
-    return getaddrinfo(name, NULL, &hints, result);
+    return fm_getaddrinfo(name, NULL, &hints, result);
 }
 
 /* XXX FIXME: doesn't detect if an IPv6-mapped IPv4 address
@@ -77,9 +77,9 @@ static int is_ip_alias(const char *name1,const char *name2)
 
 found:
     if (res2)
-       freeaddrinfo(res2);
+       fm_freeaddrinfo(res2);
     if (res1)
-       freeaddrinfo(res1);
+       fm_freeaddrinfo(res1);
     return rc;
 }
 
@@ -160,16 +160,16 @@ int is_host_alias(const char *name, struct query *ctl, struct addrinfo **res)
     hints.ai_socktype=SOCK_STREAM;
     hints.ai_flags=AI_CANONNAME;
 
-    e = getaddrinfo(name, NULL, &hints, res);
+    e = fm_getaddrinfo(name, NULL, &hints, res);
     if (e == 0)
     {
        int rr = (strcasecmp(ctl->server.truename, (*res)->ai_canonname) == 0);
-       freeaddrinfo(*res); *res = NULL;
+       fm_freeaddrinfo(*res); *res = NULL;
        if (rr)
            goto match;
-        else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
+        else if (ctl->server.checkalias && 0 == fm_getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
        {
-           freeaddrinfo(res_st);
+           fm_freeaddrinfo(res_st);
            if (outlevel >= O_DEBUG)
                report(stdout, GT_("Checking if %s is really the same node as %s\n"),ctl->server.truename,name);
            if (is_ip_alias(ctl->server.truename,name) == TRUE)
index 03d0b33c7fd77db405b1f6f24baea82c9463c549..e5012850c71f50850b90d46b69a1e442be4e7aa2 100644 (file)
@@ -5,7 +5,7 @@ dnl
 dnl Process this file with autoconf to produce a configure script.
 dnl
 
-AC_INIT([fetchmail],[6.3.5-beta1],[fetchmail-users@lists.berlios.de])
+AC_INIT([fetchmail],[6.3.5-beta2],[fetchmail-users@lists.berlios.de])
 AC_CONFIG_SRCDIR([fetchmail.h])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_LIBOBJ_DIR([.])
@@ -138,7 +138,7 @@ AC_SUBST(EXTRAOBJ)
 
 AC_CHECK_FUNCS(tcsetattr stty setsid geteuid seteuid dnl
   strerror syslog snprintf vprintf vsnprintf vsyslog dnl
-  atexit inet_aton strftime setrlimit socketpair sigprocmask dnl
+  atexit inet_aton strftime setrlimit socketpair dnl
   sigaction strdup setlocale)
 
 AC_CHECK_DECLS(strerror)
@@ -428,6 +428,22 @@ AC_CHECK_FUNCS(getnameinfo inet_ntop)
 AM_CONDITIONAL(NEED_GETADDRINFO, test "$ac_cv_search_getaddrinfo" != "none required")
 AM_CONDITIONAL(NEED_GETNAMEINFO, test "$ac_cv_func_getnameinfo"   != yes)
 
+dnl Check if getaddrinfo is async-signal-safe - most implementations aren't
+if test "$ac_cv_search_getaddrinfo" = "none required" ; then
+    AC_MSG_CHECKING(if your getaddrinfo is async-signal-safe)
+    gai_ts=no
+    dnl we have getaddrinfo() - check if the OS is known to have a async-signal-safe implementation
+    case $target_os in
+       linux*)                                 gai_ts=yes ;;
+       freebsd5.5|freebsd6*|freebsd7*)         gai_ts=yes ;;
+       solaris2.8|solaris2.9|solaris2.10)      gai_ts=yes ;;
+    esac
+    AC_MSG_RESULT($gai_ts)
+    if test $gai_ts = yes ; then
+       AC_DEFINE(GETADDRINFO_ASYNCSAFE, 1, [define to 1 if you know your getaddrinfo function is async-signal-safe])
+    fi
+fi
+
 # This version of the Kerberos 4 and 5 options addresses the follwing issues:
 # 
 # * Build correctly under Heimdal kerberos if it is compiled with db2 and
index ae4b7e69c380dfc59ae2b374eb1ce53e9c2e5370..d3c8c97025e3bd4cc3289cafc9d07743c11c6f58 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -862,11 +862,11 @@ static int do_session(
        sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
 
        if (ai0) {
-           freeaddrinfo(ai0); ai0 = NULL;
+           fm_freeaddrinfo(ai0); ai0 = NULL;
        }
 
        if (ai1) {
-           freeaddrinfo(ai1); ai1 = NULL;
+           fm_freeaddrinfo(ai1); ai1 = NULL;
        }
        
        if (js == THROW_TIMEOUT)
@@ -998,7 +998,7 @@ static int do_session(
                hints.ai_family = AF_UNSPEC;
                hints.ai_flags = AI_CANONNAME;
 
-               error = getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
+               error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
                if (error)
                {
                    report(stderr,
@@ -1024,7 +1024,7 @@ static int do_session(
                    ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
                    ctl->server.trueaddr_len = res->ai_addrlen;
                    memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
-                   freeaddrinfo(res);
+                   fm_freeaddrinfo(res);
                }
            }
        }
diff --git a/env.c b/env.c
index 85c992c08e7edde6cfaf3289cae5693e2ed0bf21..9b9e608cfafbf5410754d1c3df4a1918687874d4 100644 (file)
--- a/env.c
+++ b/env.c
@@ -161,7 +161,7 @@ char *host_fqdn(int required)
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags=AI_CANONNAME;
 
-       e = getaddrinfo(tmpbuf, NULL, &hints, &res);
+       e = fm_getaddrinfo(tmpbuf, NULL, &hints, &res);
        if (e) {
            /* exit with error message */
            fprintf(stderr,
@@ -177,7 +177,7 @@ char *host_fqdn(int required)
        }
 
        result = xstrdup(res->ai_canonname);
-       freeaddrinfo(res);
+       fm_freeaddrinfo(res);
     }
     else
        result = xstrdup(tmpbuf);
index 7c63e22a8396d8f561a054e7f137f2fa6c987e04..cfe6a634af9e712a9b2ef58196f14f8ffea9501c 100644 (file)
@@ -759,5 +759,8 @@ int servport(const char *service);
 # define NI_DGRAM      16
 #endif
 
+int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res);
+void fm_freeaddrinfo(struct addrinfo *ai);
+
 #endif
 /* fetchmail.h ends here */
diff --git a/fm_getaddrinfo.c b/fm_getaddrinfo.c
new file mode 100644 (file)
index 0000000..97cec65
--- /dev/null
@@ -0,0 +1,40 @@
+#include "config.h"
+#include "fetchmail.h"
+#include "i18n.h"
+
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+
+/** This is a getaddrinfo() replacement that blocks SIGALRM,
+ * to avoid issues with non-reentrant getaddrinfo() implementations
+ * after SIGALRM timeouts, for instance on MacOS X or NetBSD. */
+int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res)
+{
+    int rc;
+
+#ifndef GETADDRINFO_ASYNCSAFE
+    sigset_t ss, os;
+
+    sigemptyset(&ss);
+    sigaddset(&ss, SIGALRM);
+
+    if (sigprocmask(SIG_BLOCK, &ss, &os))
+       report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno));
+#endif
+
+    rc = getaddrinfo(node, serv, hints, res);
+
+#ifndef GETADDRINFO_ASYNCSAFE
+    if (sigprocmask(SIG_SETMASK, &os, NULL))
+       report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno));
+#endif
+
+    return rc;
+}
+
+/** this is a debugging freeaddrinfo() wrapper. */
+void fm_freeaddrinfo(struct addrinfo *ai)
+{
+    freeaddrinfo(ai);
+}
index 2849f7c2d766f98187647b8e66529e45f188260a..0a12c640446b35dfa42e8e1405367db85784be84 100644 (file)
@@ -48,7 +48,7 @@ int servport(const char *service) {
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
-       e = getaddrinfo(NULL, service, &hints, &res);
+       e = fm_getaddrinfo(NULL, service, &hints, &res);
        if (e) {
            report(stderr, GT_("getaddrinfo(NULL, \"%s\") error: %s\n"),
                    service, gai_strerror(e));
@@ -64,10 +64,10 @@ int servport(const char *service) {
                break;
 #endif
                default:
-                   freeaddrinfo(res);
+                   fm_freeaddrinfo(res);
                    goto err;
            }
-           freeaddrinfo(res);
+           fm_freeaddrinfo(res);
        }
     } else {
        if (u == 0 || u > 65535)
index 080f18887d0708ea556ee4c39b1769524ccb477c..52e9f1cf9815464926b880de315eec7726e73367 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -277,7 +277,7 @@ int SockOpen(const char *host, const char *service,
     memset(&req, 0, sizeof(struct addrinfo));
     req.ai_socktype = SOCK_STREAM;
 
-    i = getaddrinfo(host, service, &req, ai0);
+    i = fm_getaddrinfo(host, service, &req, ai0);
     if (i) {
        report(stderr, GT_("getaddrinfo(\"%s\",\"%s\") error: %s\n"),
                host, service, gai_strerror(i));
@@ -340,7 +340,7 @@ int SockOpen(const char *host, const char *service,
        break;
     }
 
-    freeaddrinfo(*ai0);
+    fm_freeaddrinfo(*ai0);
     *ai0 = NULL;
 
     if (i == -1)