aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-service.c')
-rw-r--r--camel/camel-service.c148
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)