Compare commits

...

10 Commits

Author SHA1 Message Date
Oswald Buddenhagen
65cd4429bb document defaults of referenced XDG env vars
so users don't have to google the spec.
2022-07-09 08:28:45 +02:00
Oswald Buddenhagen
8648d7a479 remove duplicate contributor entry
anton khirnov is already in the main section, no need to have him in the
honorary section as well.

on a completely unrelated note, for posterity: andreas grapentin's
mention is due to commit cf13630a, where i forgot to credit him for the
initial version of the patch.
2022-07-05 11:40:54 +02:00
Oswald Buddenhagen
ec50c55c36 make DNS lookup asynchronous
true asynchronicity is actually fairly useless, as it's unlikely that
both Stores in a Channel use IMAP, and both host resolutions take
particularly long - the main objective is imposing the Timeout setting.
however, we can't just use setjmp()+alarm(), as longjmp()ing out of
getaddrinfo() is undefined, as it may for example free() just at the
wrong time. so we go for the real thing.

this implementation just fork()s out a process which uses getaddrinfo()
(or gethostbyname()) per lookup. this isn't particularly scalable, but
as we don't expect a lot of lookups, it seems adequate.
2022-07-04 18:28:30 +02:00
Oswald Buddenhagen
ced20ad0d9 fix Tunnel leaving behind zombies
this generally went unnoticed, as the tunnel usually terminates right
before we exit anyway. however, if multiple Channels are synced, it may
become visible.

this is a "shotgun" implementation, where the main loop just reaps all
unclaimed children.
arguably, it would be cleaner if each socket actually tracked its own
process, but getting synchronous kills+waits right is tricky, so we
continue to pretend that there is no process as far as the socket layer
is concerned.

poll()/select() are not restartable, so they need EINTR handling now
that SIGCHLD is actually delivered.
2022-07-04 18:28:30 +02:00
Oswald Buddenhagen
b841374827 fix broken Tunnel potentially causing SIGPIPE
we need to ignore the signal, so the regular error handling can kick in.
2022-07-04 18:28:30 +02:00
Oswald Buddenhagen
b9a4746b54 don't refresh progress counters pointlessly
the mainloop-based refresh timer keeps spinning even if there is no
update. overload stats_steps to signal whether a refresh is needed.

amends 8fbc4323.
2022-07-04 18:28:30 +02:00
Oswald Buddenhagen
460bfbb8ac abort channel sync when a store is fubar
this got lost in d5a5da947.

this also simplifies a nested condition, where the logic has previously
been, but isn't applicable any more.

REFMAIL: 87fsjloz05.fsf@wavexx.thregr.org
2022-07-01 15:13:10 +02:00
Oswald Buddenhagen
92faccc639 improve wording of --ext-exit docu 2022-07-01 14:57:39 +02:00
Oswald Buddenhagen
f6ccf9c4f5 fix lineup of --ext-exit in help output 2022-07-01 14:57:39 +02:00
Oswald Buddenhagen
16ecde504d try to make AUTHORS reflect reality
make a complete list of contributors who hold copyright (and those who
don't).

the case of ted is particularly interesting - he recently disclaimed
significant contributions, but it turns out that this isn't true:
the rewrite in 130664b6 incorporated significant portions of his async
IMAP patch for debian.

speaking of debian, i deleted ted's and nicolas' mention as debian
maintainers, as debian/ is basically just a (poorly maintained) mirror,
and has an own copyright file.
2022-06-26 12:21:58 +02:00
9 changed files with 369 additions and 129 deletions

108
AUTHORS
View File

@ -1,17 +1,101 @@
Oswald Buddenhagen <ossi@users.sf.net>
* Contributor, current maintainer
Theodore Ts'o <tytso@mit.edu>
* Contributor, Debian package co-maintainer
Nicolas Boullis <nboullis@debian.org>
* Debian package maintainer and minor upstream contributions
Michael Elkins <me@mutt.org>
* Original author
Contact
=======
Send questions and bug reports to the isync-devel@lists.sourceforge.net
mailing list.
_DON'T_ report bugs to Michael, not even in a CC: - he is not actively
Do _NOT_ report bugs to Michael, not even in a CC: - he is not actively
involved in isync development any more.
Lead Developers
===============
Oswald Buddenhagen <ossi@users.sf.net>
- Current maintainer
Michael Elkins <me@mutt.org>
- Original author
Contributors
============
(Some of these people also contributed bugfixes and optimizations.)
(In chronological order.)
Jeremy Katz <katzj@linuxpower.org>
- UseNamespace & UseSSL* options
Daniel Resare <noa@metamatrix.se>
- Numerous SSL handling improvements
Eivind Eklund <eivind@FreeBSD.org>
- MaxMessages option
Theodore Ts'o <tytso@mit.edu>
- get-cert script
- Maildir UID mapping improvements
- Initial version of partial async IMAP support
Marc Hoersken <info@marc-hoersken.de>
- CopyArrivalDate option
Jack Stone <jwjstone@fastmail.fm>
Jan Synacek <jsynacek@redhat.com>
- SASL support
Jesse Weaver <pianohacker@gmail.com>
- IMAP stream compression support
Anton Khirnov <anton@khirnov.net>
- ClientKey & ClientCertificate options
Michael J Gruber <github@grubix.eu>
- Support for the $Forwarded/Passed flag
Patrick Steinhardt <ps@pks.im>
- UserCmd option
Oliver Runge <oliver.runge@gmail.com>
- UseKeychain option
Georgy Kibardin <georgy@kibardin.name>
- Support for UTF-7 IMAP mailbox names
Honorary Contributors
=====================
(These people contributed patches that were too small or obvious
to claim copyright, or were rewritten from scratch.)
(In alphabetical order.)
Alessandro Ghedini <ghedo@debian.org>
Andreas Grapentin <andreas@grapentin.org>
Aurélien Francillon <aurelien.francillon@eurecom.fr>
Ben Kibbey <bjk@luxsci.net>
Caspar Schutijser <caspar@schutijser.com>
Cedric Ware <cedric.ware__bml@normalesup.org>
Dmitrij D. Czarkoff <czarkoff@gmail.com>
Dmitry Torokhov <dtor@chromium.org>
Felipe Contreras <felipe.contreras@gmail.com>
Felix Janda <felix.janda@posteo.de>
Gergely Risko <gergely@risko.hu>
Sung Pae "guns" <self@sungpae.com>
Helmut Grohne <helmut@subdivi.de>
Hugo Haas <hugo@larve.net>
Jaroslav Suchanek <jaroslav.suchanek@gmail.com>
Jeremie Courreges-Anglas <jca@openbsd.org>
Klemens Nanni <kn@openbsd.org>
Lorenzo Martignoni <lorenzo.martignoni@technologist.com>
Magnus Jonsson <bigfoot@acc.umu.se>
Marcin Niestroj <macius1990w@gmail.com>
Martin Stenberg <martin@gnutiken.se>
Mike Delaney <mdelan@lusars.net>
Nicolas Boullis <nboullis@debian.org>
Nihal Jere <nihal@nihaljere.xyz>
Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Remko Tronçon <remko@el-tramo.be>
sbfnk@users.sf.net
Thomas Roessler <roessler@does-not-exist.org>
Todd T. Fries <todd@fries.net>
Vincent Bernat <vincent@bernat.ch>
Yuri D'Elia <wavexx@thregr.org>

View File

@ -89,6 +89,26 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
exit( code );
}
static int child_pipe[2];
static notifier_t child_notifier;
static void
childHandler( int n ATTR_UNUSED )
{
// We can't just reap everything here, as we might steal children
// from popen(). Let the main loop handle it synchronously instead.
char dummy = 0;
write( child_pipe[1], &dummy, 1 );
}
static void
childReaper( int events ATTR_UNUSED, void *aux ATTR_UNUSED )
{
char dummy;
while (read( child_pipe[0], &dummy, 1 ) == 1) {}
while (waitpid( -1, NULL, WNOHANG ) > 0) {}
}
#ifdef __linux__
static void ATTR_NORETURN
crashHandler( int n )
@ -541,9 +561,31 @@ main( int argc, char **argv )
if (load_config( config ))
return 1;
signal( SIGPIPE, SIG_IGN );
if (pipe( child_pipe )) {
perror( "pipe" );
return 1;
}
fcntl( child_pipe[0], F_SETFL, O_NONBLOCK );
fcntl( child_pipe[1], F_SETFL, O_NONBLOCK );
init_notifier( &child_notifier, child_pipe[0], childReaper, NULL );
conf_notifier( &child_notifier, 0, POLLIN );
struct sigaction sa = { 0 };
sa.sa_handler = childHandler;
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
sigaction( SIGCHLD, &sa, NULL );
if (mvars->list_stores)
list_stores( mvars, argv + oind );
else
sync_chans( mvars, argv + oind );
return mvars->ret;
}
void
cleanup_mainloop( void )
{
cleanup_drivers();
wipe_notifier( &child_notifier );
}

View File

@ -126,7 +126,7 @@ do_list_stores( list_vars_t *lvars )
next:
advance_store( lvars );
}
cleanup_drivers();
cleanup_mainloop();
}
static void

View File

@ -21,5 +21,6 @@ typedef struct {
void sync_chans( core_vars_t *cvars, char **argv );
void list_stores( core_vars_t *cvars, char **argv );
void cleanup_mainloop( void );
#endif

View File

@ -43,9 +43,11 @@ print_stats( void )
static void
stats_timeout( void *aux ATTR_UNUSED )
{
if (stats_steps != -1) {
stats_steps = -1;
conf_wakeup( &stats_wakeup, 200 );
print_stats();
}
conf_wakeup( &stats_wakeup, 200 );
}
void
@ -55,8 +57,10 @@ stats( void )
return;
// If the main loop appears to be running, skip the sync path.
if (stats_steps < 0)
if (stats_steps < 0) {
stats_steps = -2;
return;
}
// Rate-limit the (somewhat) expensive timer queries.
if (++stats_steps < 10)
@ -492,7 +496,7 @@ do_sync_chans( main_vars_t *mvars )
next:
advance_chan( mvars );
}
cleanup_drivers();
cleanup_mainloop();
if (!mvars->cvars->list && (DFlags & PROGRESS))
wipe_wakeup( &stats_wakeup );
}
@ -668,7 +672,7 @@ static void
do_sync_boxes( main_vars_t *mvars )
{
mvars->box_cben = 0;
for (;;) {
while (mvars->state[F] == ST_OPEN && mvars->state[N] == ST_OPEN) {
if (mvars->chanptr->boxlist) {
box_ent_t *mbox = mvars->boxptr;
if (!mbox)
@ -730,13 +734,11 @@ done_sync( int sts, void *aux )
stats();
if (sts) {
mvars->cvars->ret = 1;
if (sts & (SYNC_BAD(F) | SYNC_BAD(N))) {
if (sts & SYNC_BAD(F))
mvars->state[F] = ST_CLOSED;
if (sts & SYNC_BAD(N))
mvars->state[N] = ST_CLOSED;
}
}
mvars->box_done = 1;
if (mvars->box_cben)
do_sync_boxes( mvars );

View File

@ -36,6 +36,7 @@ Multiple replicas of each mailbox can be maintained.
Read configuration from \fIfile\fR.
By default, the configuration is read from $XDG_CONFIG_HOME/isyncrc, and
if that does not exist, ~/.mbsyncrc is tried in turn.
$XDG_CONFIG_HOME defaults to ~/.config if not set.
.TP
\fB-a\fR, \fB--all\fR
Select all configured Channels. Any Channel/Group specifications on the
@ -80,8 +81,10 @@ operations are determined, but no modifications are actually made
to either the mailboxes or the state files.
.TP
\fB-e\fR, \fB--ext-exit\fR
Return an extended exit code: Add 32 resp. 64 to the code if any
modifications were made on the far resp. near side.
Return an extended exit code: Add 32 or 64 to the code if any
modifications were made on the far or near side, respectively; these
are not mutually exclusive, so the code may be 96 if changes were both
pushed and pulled.
An error may be reported at the same time, so the code may be for example
65 if some changes were successfully pulled, while others failed.
.TP
@ -730,7 +733,8 @@ the appended string is made up according to the pattern
(see also \fBFieldDelimiter\fR below).
.br
(Global default: \fI$XDG_STATE_HOME/isync/\fR, with a fallback to
\fI~/.mbsync/\fR if only that exists)
\fI~/.mbsync/\fR if only that exists.
$XDG_STATE_HOME defaults to ~/.local/state if not set.)
.
.SS Groups
.TP
@ -856,11 +860,11 @@ There is no risk as long as the IMAP mailbox is accessed by only one client
.
.SH FILES
.TP
.B $XDG_CONFIG_HOME/isyncrc
\fB$XDG_CONFIG_HOME/isyncrc\fR (usually \fB~/.config/isyncrc\fR)
Default configuration file.
See also the example file in the documentation directory.
.TP
.B $XDG_STATE_HOME/isync/
\fB$XDG_STATE_HOME/isync/\fR (usually \fB~/.local/state/isync/\fR)
Directory containing synchronization state files.
.TP
.B ~/.mbsyncrc

View File

@ -28,6 +28,7 @@
#endif
enum {
SCK_RESOLVING,
SCK_CONNECTING,
#ifdef HAVE_LIBSSL
SCK_STARTTLS,
@ -415,6 +416,7 @@ static void socket_fd_cb( int, void * );
static void socket_fake_cb( void * );
static void socket_timeout_cb( void * );
static void socket_resolve( conn_t * );
static void socket_connect_one( conn_t * );
static void socket_connect_next( conn_t * );
static void socket_connect_failed( conn_t * );
@ -422,15 +424,21 @@ static void socket_connected( conn_t * );
static void socket_connect_bail( conn_t * );
static void
socket_open_internal( conn_t *sock, int fd )
socket_register_internal( conn_t *sock, int fd )
{
sock->fd = fd;
fcntl( fd, F_SETFL, O_NONBLOCK );
init_notifier( &sock->notify, fd, socket_fd_cb, sock );
init_wakeup( &sock->fd_fake, socket_fake_cb, sock );
init_wakeup( &sock->fd_timeout, socket_timeout_cb, sock );
}
static void
socket_open_internal( conn_t *sock, int fd )
{
fcntl( fd, F_SETFL, O_NONBLOCK );
socket_register_internal( sock, fd );
}
static void
socket_close_internal( conn_t *sock )
{
@ -441,32 +449,6 @@ socket_close_internal( conn_t *sock )
sock->fd = -1;
}
#ifndef HAVE_IPV6
struct addr_info {
struct addr_info *ai_next;
struct sockaddr_in ai_addr[1];
};
#define freeaddrinfo(ai) free( ai )
static struct addr_info *
init_addrinfo( struct hostent *he )
{
uint naddr = 0;
for (char **addr = he->h_addr_list; *addr; addr++)
naddr++;
struct addr_info *caddr = nfzalloc( naddr * sizeof(struct addrinfo) );
struct addr_info *ret, **caddrp = &ret;
for (char **addr = he->h_addr_list; *addr; addr++, caddr++) {
caddr->ai_addr->sin_family = AF_INET;
memcpy( &caddr->ai_addr->sin_addr.s_addr, *addr, sizeof(struct in_addr) );
*caddrp = caddr;
caddrp = &caddr->ai_next;
}
return ret;
}
#endif
void
socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
{
@ -501,77 +483,202 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
info( "\vok\n" );
socket_connected( sock );
} else {
#ifdef HAVE_IPV6
int gaierr;
struct addrinfo hints;
socket_resolve( sock );
}
}
memset( &hints, 0, sizeof(hints) );
static void
pipe_write( int fd, void *buf, int len )
{
do {
int wrote = write( fd, buf, len );
if (wrote < 0) {
perror( "write" );
_exit( 1 );
}
buf = ((char *)buf) + wrote;
len -= wrote;
} while (len);
}
static void
socket_resolve( conn_t *sock )
{
info( "Resolving %s...\n", sock->conf->host );
int pfd[2];
if (pipe( pfd )) {
perror( "pipe" );
exit( 1 );
}
switch (fork()) {
case -1:
perror( "fork" );
exit( 1 );
case 0:
break;
default:
close( pfd[1] );
socket_register_internal( sock, pfd[0] );
sock->state = SCK_RESOLVING;
conf_notifier( &sock->notify, 0, POLLIN );
socket_expect_activity( sock, 1 );
return;
}
#ifdef HAVE_IPV6
struct addrinfo *res, hints = { 0 };
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
infon( "Resolving %s... ", conf->host );
if ((gaierr = getaddrinfo( conf->host, NULL, &hints, &sock->addrs ))) {
error( "Error: Cannot resolve server '%s': %s\n", conf->host, gai_strerror( gaierr ) );
socket_connect_bail( sock );
return;
int gaierr = getaddrinfo( sock->conf->host, NULL, &hints, &res );
pipe_write( pfd[1], &gaierr, sizeof(gaierr) );
if (gaierr)
_exit( 1 );
static_assert( sizeof(((struct addrinfo){ 0 }).ai_family) == sizeof(int), "unexpected size of ai_family" );
static_assert( sizeof(struct in_addr) % sizeof(int) == 0, "unexpected size of struct in_addr" );
static_assert( sizeof(struct in6_addr) % sizeof(int) == 0, "unexpected size of struct in6_addr" );
int nbytes = 0;
for (struct addrinfo *cres = res; cres; cres = cres->ai_next) {
if (cres->ai_family == AF_INET) {
nbytes += sizeof(int) + sizeof(struct in_addr);
} else {
assert( cres->ai_family == AF_INET6 );
nbytes += sizeof(int) + sizeof(struct in6_addr);
}
}
pipe_write( pfd[1], &nbytes, sizeof(nbytes) );
for (struct addrinfo *cres = res; cres; cres = cres->ai_next) {
pipe_write( pfd[1], &cres->ai_family, sizeof(int) );
if (cres->ai_family == AF_INET)
pipe_write( pfd[1], &((struct sockaddr_in *)cres->ai_addr)->sin_addr, sizeof(struct in_addr) );
else
pipe_write( pfd[1], &((struct sockaddr_in6 *)cres->ai_addr)->sin6_addr, sizeof(struct in6_addr) );
}
info( "\vok\n" );
#else
struct hostent *he;
struct hostent *he = gethostbyname( sock->conf->host );
int herrno = he ? 0 : h_errno;
pipe_write( pfd[1], &herrno, sizeof(herrno) );
if (!he)
_exit( 1 );
static_assert( sizeof(struct in_addr) % sizeof(int) == 0, "unexpected size of struct in_addr" );
int nbytes = 0;
for (char **addr = he->h_addr_list; *addr; addr++)
nbytes += sizeof(struct in_addr);
pipe_write( pfd[1], &nbytes, sizeof(nbytes) );
for (char **addr = he->h_addr_list; *addr; addr++)
pipe_write( pfd[1], *addr, sizeof(struct in_addr) );
#endif
_exit( 0 );
}
infon( "Resolving %s... ", conf->host );
he = gethostbyname( conf->host );
if (!he) {
error( "Error: Cannot resolve server '%s': %s\n", conf->host, hstrerror( h_errno ) );
static void
pipe_read( int fd, void *buf, int len )
{
do {
int didrd = read( fd, buf, len );
if (didrd < 0) {
sys_error( "read" );
exit( 1 );
}
if (!didrd) {
error( "read: unexpected EOF\n" );
exit( 1 );
}
buf = ((char *)buf) + didrd;
len -= didrd;
} while (len);
}
static void
socket_resolve_finalize( conn_t *sock )
{
int errcode;
pipe_read( sock->fd, &errcode, sizeof(errcode) );
if (errcode) {
#ifdef HAVE_IPV6
const char *err = gai_strerror( errcode );
#else
const char *err = hstrerror( errcode );
#endif
error( "Error: Cannot resolve server '%s': %s\n", sock->conf->host, err );
socket_close_internal( sock );
socket_connect_bail( sock );
return;
}
info( "\vok\n" );
sock->addrs = init_addrinfo( he );
#endif
sock->curr_addr = sock->addrs;
int nbytes;
pipe_read( sock->fd, &nbytes, sizeof(nbytes) );
char *addrs = nfmalloc( nbytes );
pipe_read( sock->fd, addrs, nbytes );
sock->curr_addr = sock->addrs = addrs;
sock->addrs_end = addrs + nbytes;
socket_close_internal( sock ); // Get rid of the pipe
socket_connect_one( sock );
}
}
static void
socket_resolve_timeout( conn_t *sock )
{
error( "Error: Cannot resolve server '%s': timeout.\n", sock->conf->host );
socket_close_internal( sock );
socket_connect_bail( sock );
}
static void
socket_connect_one( conn_t *sock )
{
int s;
#ifdef HAVE_IPV6
struct addrinfo *ai;
#else
struct addr_info *ai;
#endif
if (!(ai = sock->curr_addr)) {
char *ai = sock->curr_addr;
if (ai == sock->addrs_end) {
error( "No working address found for %s\n", sock->conf->host );
socket_connect_bail( sock );
return;
}
union {
struct sockaddr any;
struct sockaddr_in ip4;
#ifdef HAVE_IPV6
if (ai->ai_family == AF_INET6) {
struct sockaddr_in6 *in6 = ((struct sockaddr_in6 *)ai->ai_addr);
struct sockaddr_in6 ip6;
#endif
} addr;
#ifdef HAVE_IPV6
int fam = *(int *)ai;
ai += sizeof(int);
int addr_len;
if (fam == AF_INET6) {
addr_len = sizeof(addr.ip6);
addr.ip6.sin6_addr = *(struct in6_addr *)ai;
addr.ip6.sin6_flowinfo = 0;
addr.ip6.sin6_scope_id = 0;
ai += sizeof(struct in6_addr);
} else {
addr_len = sizeof(addr.ip4);
#else
const int fam = AF_INET;
const int addr_len = sizeof(addr.ip4);
{
#endif
addr.ip4.sin_addr = *(struct in_addr *)ai;
ai += sizeof(struct in_addr);
}
sock->curr_addr = ai;
#ifdef HAVE_IPV6
if (fam == AF_INET6) {
char sockname[64];
in6->sin6_port = htons( sock->conf->port );
inet_ntop( fam, &addr.ip6.sin6_addr, sockname, sizeof(sockname) );
nfasprintf( &sock->name, "%s ([%s]:%hu)",
sock->conf->host, inet_ntop( AF_INET6, &in6->sin6_addr, sockname, sizeof(sockname) ), sock->conf->port );
sock->conf->host, sockname, sock->conf->port );
} else
#endif
{
struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
in->sin_port = htons( sock->conf->port );
nfasprintf( &sock->name, "%s (%s:%hu)",
sock->conf->host, inet_ntoa( in->sin_addr ), sock->conf->port );
sock->conf->host, inet_ntoa( addr.ip4.sin_addr ), sock->conf->port );
}
#ifdef HAVE_IPV6
s = socket( ai->ai_family, SOCK_STREAM, 0 );
#else
s = socket( PF_INET, SOCK_STREAM, 0 );
#endif
int s = socket( fam, SOCK_STREAM, 0 );
if (s < 0) {
socket_connect_next( sock );
return;
@ -579,11 +686,9 @@ socket_connect_one( conn_t *sock )
socket_open_internal( sock, s );
infon( "Connecting to %s... ", sock->name );
#ifdef HAVE_IPV6
if (connect( s, ai->ai_addr, ai->ai_addrlen )) {
#else
if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) {
#endif
addr.any.sa_family = fam;
addr.ip4.sin_port = htons( sock->conf->port ); // Aliased for ip6
if (connect( s, &addr.any, addr_len )) {
if (errno != EINPROGRESS) {
socket_connect_failed( sock );
return;
@ -604,7 +709,6 @@ socket_connect_next( conn_t *conn )
sys_error( "Cannot connect to %s", conn->name );
free( conn->name );
conn->name = NULL;
conn->curr_addr = conn->curr_addr->ai_next;
socket_connect_one( conn );
}
@ -618,10 +722,8 @@ socket_connect_failed( conn_t *conn )
static void
socket_connected( conn_t *conn )
{
if (conn->addrs) {
freeaddrinfo( conn->addrs );
free( conn->addrs );
conn->addrs = NULL;
}
conf_notifier( &conn->notify, 0, POLLIN );
socket_expect_activity( conn, 0 );
conn->state = SCK_READY;
@ -631,10 +733,8 @@ socket_connected( conn_t *conn )
static void
socket_cleanup_names( conn_t *conn )
{
if (conn->addrs) {
freeaddrinfo( conn->addrs );
free( conn->addrs );
conn->addrs = NULL;
}
free( conn->name );
conn->name = NULL;
}
@ -1106,6 +1206,11 @@ socket_fd_cb( int events, void *aux )
{
conn_t *conn = (conn_t *)aux;
if (conn->state == SCK_RESOLVING) {
socket_resolve_finalize( conn );
return;
}
if ((events & POLLERR) || conn->state == SCK_CONNECTING) {
int soerr;
socklen_t selen = sizeof(soerr);
@ -1168,7 +1273,9 @@ socket_timeout_cb( void *aux )
{
conn_t *conn = (conn_t *)aux;
if (conn->state == SCK_CONNECTING) {
if (conn->state == SCK_RESOLVING) {
socket_resolve_timeout( conn );
} else if (conn->state == SCK_CONNECTING) {
errno = ETIMEDOUT;
socket_connect_failed( conn );
} else {

View File

@ -57,11 +57,7 @@ typedef struct {
int fd;
int state;
const server_conf_t *conf; /* needed during connect */
#ifdef HAVE_IPV6
struct addrinfo *addrs, *curr_addr; /* needed during connect */
#else
struct addr_info *addrs, *curr_addr; /* needed during connect */
#endif
char *addrs, *addrs_end, *curr_addr; // needed during connect; assumed to be int-aligned
char *name;
#ifdef HAVE_LIBSSL
SSL *ssl;

View File

@ -1110,6 +1110,8 @@ event_wait( void )
case 0:
return;
case -1:
if (errno == EINTR)
return;
perror( "poll() failed in event loop" );
abort();
default:
@ -1162,6 +1164,8 @@ event_wait( void )
case 0:
return;
case -1:
if (errno == EINTR)
return;
perror( "select() failed in event loop" );
abort();
default: