diff options
Diffstat (limited to 'camel/camel-service.c')
-rw-r--r-- | camel/camel-service.c | 148 |
1 files changed, 87 insertions, 61 deletions
diff --git a/camel/camel-service.c b/camel/camel-service.c index f3d2a43572..78c9fe5da6 100644 --- a/camel/camel-service.c +++ b/camel/camel-service.c @@ -691,6 +691,7 @@ struct _lookup_msg { #ifdef ENABLE_THREADS EMsg msg; #endif + unsigned int cancelled:1; const char *name; int len; int type; @@ -718,7 +719,13 @@ get_hostbyname(void *data) d(printf("gethostbyname ok?\n")); #ifdef ENABLE_THREADS - e_msgport_reply((EMsg *)info); + /* If we got cancelled, dont reply, just free it */ + if (info->cancelled) { + g_free(info->hostbufmem); + g_free(info); + } else { + e_msgport_reply((EMsg *)info); + } #endif return NULL; } @@ -766,27 +773,33 @@ camel_gethostbyname (const char *name, CamelException *ex) FD_SET(cancel_fd, &rdset); FD_SET(fd, &rdset); fdmax = MAX(fd, cancel_fd) + 1; - status = select (fdmax, &rdset, NULL, 0, NULL); + status = select(fdmax, &rdset, NULL, 0, NULL); } while (status == -1 && errno == EINTR); - - if (status == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failure in name lookup: %s"), - g_strerror (errno)); - d(printf("Cancelling lookup thread\n")); - pthread_cancel(id); - } else if (FD_ISSET(cancel_fd, &rdset)) { - d(printf("Cancelling lookup thread\n")); - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + + if (status == -1 || FD_ISSET(cancel_fd, &rdset)) { + if (status == -1) + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Failure in name lookup: %s"), g_strerror(errno)); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + + /* We cancel so if the thread impl is decent it causes immediate exit. + We detach so we dont need to wait for it to exit if it isn't. + We check the reply port incase we had a reply in the mean time, which we free later */ + d(printf("Cancelling lookup thread and leaving it\n")); + msg->cancelled = 1; + pthread_detach(id); pthread_cancel(id); + msg = (struct _lookup_msg *)e_msgport_get(reply_port); } else { struct _lookup_msg *reply = (struct _lookup_msg *)e_msgport_get(reply_port); g_assert(reply == msg); + d(printf("waiting for child to exit\n")); + pthread_join(id, NULL); + d(printf("child done\n")); } - d(printf("waiting for child to exit\n")); - pthread_join(id, NULL); - d(printf("child done\n")); + } else { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: cannot create thread: %s"), g_strerror(errno)); } e_msgport_destroy(reply_port); } @@ -794,23 +807,25 @@ camel_gethostbyname (const char *name, CamelException *ex) camel_operation_end(NULL); - if (msg->result != 0) { - if (!camel_exception_is_set(ex)) { - if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: %s: host not found"), name); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: %s: unknown reason"), name); - } + if (!camel_exception_is_set(ex)) { + if (msg->result == 0) + return &msg->hostbuf; + + if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Host lookup failed: %s: host not found"), name); + else + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Host lookup failed: %s: unknown reason"), name); + } + + if (msg) { g_free(msg->hostbufmem); g_free(msg); - return NULL; - } else { - return &msg->hostbuf; } -} + return NULL; +} static void * get_hostbyaddr (void *data) @@ -830,7 +845,12 @@ get_hostbyaddr (void *data) d(printf ("gethostbyaddr ok?\n")); #ifdef ENABLE_THREADS - e_msgport_reply ((EMsg *) info); + if (info->cancelled) { + g_free(info->hostbufmem); + g_free(info); + } else { + e_msgport_reply((EMsg *)info); + } #endif return NULL; } @@ -884,24 +904,28 @@ camel_gethostbyaddr (const char *addr, int len, int type, CamelException *ex) status = select (fdmax, &rdset, NULL, 0, NULL); } while (status == -1 && errno == EINTR); - if (status == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failure in name lookup: %s"), g_strerror (errno)); - d(printf ("Cancelling lookup thread\n")); - pthread_cancel (id); - } else if (FD_ISSET(cancel_fd, &rdset)) { - d(printf ("Cancelling lookup thread\n")); - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - pthread_cancel (id); + if (status == -1 || FD_ISSET(cancel_fd, &rdset)) { + if (status == -1) + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Failure in name lookup: %s"), g_strerror(errno)); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + + /* We cancel so if the thread impl is decent it causes immediate exit. + We detach so we dont need to wait for it to exit if it isn't. + We check the reply port incase we had a reply in the mean time, which we free later */ + d(printf("Cancelling lookup thread and leaving it\n")); + msg->cancelled = 1; + pthread_detach(id); + pthread_cancel(id); + msg = (struct _lookup_msg *)e_msgport_get(reply_port); } else { - struct _lookup_msg *reply = (struct _lookup_msg *) e_msgport_get (reply_port); - - g_assert (reply == msg); + struct _lookup_msg *reply = (struct _lookup_msg *)e_msgport_get(reply_port); + + g_assert(reply == msg); + d(printf("waiting for child to exit\n")); + pthread_join(id, NULL); + d(printf("child done\n")); } - - d(printf ("waiting for child to exit\n")); - pthread_join (id, NULL); - d(printf ("child done\n")); } e_msgport_destroy (reply_port); @@ -909,23 +933,25 @@ camel_gethostbyaddr (const char *addr, int len, int type, CamelException *ex) #endif camel_operation_end (NULL); - - if (msg->result != 0) { - if (!camel_exception_is_set (ex)) { - if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: host not found")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: unknown reason")); - } - - g_free (msg->hostbufmem); - g_free (msg); - return NULL; - } else { - return &msg->hostbuf; + + if (!camel_exception_is_set(ex)) { + if (msg->result == 0) + return &msg->hostbuf; + + if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Host lookup failed: host not found")); + else + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Host lookup failed: unknown reason")); } + + if (msg) { + g_free(msg->hostbufmem); + g_free(msg); + } + + return NULL; } void camel_free_host(struct hostent *h) |