Also wrap freeaddrinfo() without added functionality.
svn path=/branches/BRANCH_6-3/; revision=4895
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)
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.
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
found:
if (res2)
- freeaddrinfo(res2);
+ fm_freeaddrinfo(res2);
if (res1)
- freeaddrinfo(res1);
+ fm_freeaddrinfo(res1);
return rc;
}
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)
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([.])
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)
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
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)
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,
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);
}
}
}
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,
}
result = xstrdup(res->ai_canonname);
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
}
else
result = xstrdup(tmpbuf);
# 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 */
--- /dev/null
+#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);
+}
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));
break;
#endif
default:
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
goto err;
}
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
}
} else {
if (u == 0 || u > 65535)
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));
break;
}
- freeaddrinfo(*ai0);
+ fm_freeaddrinfo(*ai0);
*ai0 = NULL;
if (i == -1)