diff options
-rw-r--r-- | camel/ChangeLog | 28 | ||||
-rw-r--r-- | camel/camel-folder-summary.c | 4 | ||||
-rw-r--r-- | camel/camel-remote-store.c | 6 | ||||
-rw-r--r-- | camel/camel-session.c | 42 | ||||
-rw-r--r-- | camel/camel-stream-fs.c | 8 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-command.c | 9 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-private.h | 6 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 28 |
8 files changed, 114 insertions, 17 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 85e4ddef27..036bb75729 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,31 @@ +2001-01-16 Not Zed <NotZed@Ximian.com> + + * camel-folder-summary.c (camel_folder_summary_decode_string): + Chganged len back to be unsigned. And do a simple range check on + the string value to try and detect corrupted summary files. + + * providers/imap/camel-imap-command.c (imap_read_untagged): Handle + cancelled stream reads with an appropriate exception. + + * providers/imap/camel-imap-private.h: Fix the include-once + macro. Doh, confliced with camel-private.h. + + * providers/imap/camel-imap-store.c (imap_store_refresh_folders): + A copy of camel_remote_store_refresh_folders. We avoid locking + each folder when we call it though. This should be removed when i + can work out how to remove the folder lock from this function + easily. + + * camel-stream-fs.c (stream_write): Fix n' argument of select. + (stream_read): Likewise. + + * camel-remote-store.c (socket_connect): Bump the connect timeout + upto 4 minutes. + (socket_connect): Oops, fix the 'n' argument of select. + + * camel-session.c (camel_cancel_cancel): If we are given no + cancellation node, then do it for all active ones. + 2001-01-15 Jeffrey Stedfast <fejj@ximian.com> * camel-stream-fs.c (stream_close): If the close() is successful, diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index 89b18e5141..8cea0a4666 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -1375,7 +1375,7 @@ camel_folder_summary_encode_string(FILE *out, const char *str) int camel_folder_summary_decode_string(FILE *in, char **str) { - gint32 len; + guint32 len; register char *ret; io(printf("Decode string ...\n", str)); @@ -1386,7 +1386,7 @@ camel_folder_summary_decode_string(FILE *in, char **str) } len--; - if (len < 0) { + if (len > 65536) { *str = NULL; io(printf("String = '%s'\n", *str)); return -1; diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c index 9e7a60e378..993d9b5778 100644 --- a/camel/camel-remote-store.c +++ b/camel/camel-remote-store.c @@ -241,6 +241,7 @@ static int socket_connect(struct hostent *h, int port) } else { fd_set rdset, wrset; long flags; + int fdmax; fcntl(fd, F_GETFL, &flags); fcntl(fd, F_SETFL, flags | O_NONBLOCK); @@ -258,9 +259,10 @@ static int socket_connect(struct hostent *h, int port) FD_ZERO(&wrset); FD_SET(fd, &wrset); FD_SET(cancel_fd, &rdset); + fdmax = MAX(fd, cancel_fd)+1; tv.tv_usec = 0; - tv.tv_sec = 30; - if (select((fd+cancel_fd)/2+1, &rdset, &wrset, 0, &tv) == 0) { + tv.tv_sec = 60*4; + if (select(fdmax, &rdset, &wrset, 0, &tv) == 0) { close(fd); errno = ETIMEDOUT; return -1; diff --git a/camel/camel-session.c b/camel/camel-session.c index 67d58a1e67..d834bad54c 100644 --- a/camel/camel-session.c +++ b/camel/camel-session.c @@ -501,9 +501,9 @@ struct _CamelCancel { #ifdef ENABLE_THREADS #define CAMEL_CANCEL_LOCK(cc) pthread_mutex_lock(&cc->lock) -#define CAMEL_CANCEL_UNLOCK(cc) pthread_mutex_lock(&cc->lock) +#define CAMEL_CANCEL_UNLOCK(cc) pthread_mutex_unlock(&cc->lock) #define CAMEL_ACTIVE_LOCK() pthread_mutex_lock(&cancel_active_lock) -#define CAMEL_ACTIVE_UNLOCK() pthread_mutex_lock(&cancel_active_lock) +#define CAMEL_ACTIVE_UNLOCK() pthread_mutex_unlock(&cancel_active_lock) static pthread_mutex_t cancel_active_lock = PTHREAD_MUTEX_INITIALIZER; #else #define CAMEL_CANCEL_LOCK(cc) @@ -597,12 +597,27 @@ void camel_cancel_unblock(CamelCancel *cc) CAMEL_CANCEL_UNLOCK(cc); } +static void +cancel_thread(void *key, CamelCancel *cc, void *data) +{ + if (cc) + camel_cancel_cancel(cc); +} + /* cancels an operation */ void camel_cancel_cancel(CamelCancel *cc) { CamelCancelMsg *msg; - if ((cc->flags & CAMEL_CANCEL_CANCELLED) == 0) { + if (cc == NULL) { + if (cancel_active) { + CAMEL_ACTIVE_LOCK(); + g_hash_table_foreach(cancel_active, (GHRFunc)cancel_thread, NULL); + CAMEL_ACTIVE_UNLOCK(); + } + } else if ((cc->flags & CAMEL_CANCEL_CANCELLED) == 0) { + printf("cancelling thread %d\n", cc->id); + CAMEL_CANCEL_LOCK(cc); msg = g_malloc0(sizeof(*msg)); e_msgport_put(cc->cancel_port, (EMsg *)msg); @@ -630,9 +645,12 @@ void camel_cancel_register(CamelCancel *cc) cc->id = id; g_hash_table_insert(cancel_active, (void *)id, cc); - camel_cancel_ref(cc); + + printf("registering thread %d for cancellation\n", id); CAMEL_ACTIVE_UNLOCK(); + + camel_cancel_ref(cc); } /* remove a thread from being able to be cancelled */ @@ -644,7 +662,7 @@ void camel_cancel_unregister(CamelCancel *cc) cancel_active = g_hash_table_new(NULL, NULL); if (cc == NULL) { - cc = g_hash_table_lookup(cancel_active, (void *)cc->id); + cc = g_hash_table_lookup(cancel_active, (void *)pthread_self()); if (cc == NULL) { g_warning("Trying to unregister a thread that was never registered for cancellation"); } @@ -656,6 +674,9 @@ void camel_cancel_unregister(CamelCancel *cc) CAMEL_ACTIVE_UNLOCK(); if (cc) + printf("unregistering thread %d for cancellation\n", cc->id); + + if (cc) camel_cancel_unref(cc); } @@ -664,6 +685,8 @@ gboolean camel_cancel_check(CamelCancel *cc) { CamelCancelMsg *msg; + printf("checking for cancel in thread %d\n", pthread_self()); + if (cc == NULL) { if (cancel_active) { CAMEL_ACTIVE_LOCK(); @@ -674,14 +697,19 @@ gboolean camel_cancel_check(CamelCancel *cc) return FALSE; } - if (cc->blocked > 0) + if (cc->blocked > 0) { + printf("ahah! cancellation is blocked\n"); return FALSE; + } - if (cc->flags & CAMEL_CANCEL_CANCELLED) + if (cc->flags & CAMEL_CANCEL_CANCELLED) { + printf("previously cancelled\n"); return TRUE; + } msg = (CamelCancelMsg *)e_msgport_get(cc->cancel_port); if (msg) { + printf("Got cancellation message\n"); CAMEL_CANCEL_LOCK(cc); cc->flags |= CAMEL_CANCEL_CANCELLED; CAMEL_CANCEL_UNLOCK(cc); diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c index 7047670832..92c11435fa 100644 --- a/camel/camel-stream-fs.c +++ b/camel/camel-stream-fs.c @@ -227,13 +227,15 @@ stream_read (CamelStream *stream, char *buffer, size_t n) } else { fd_set rdset; long flags; + int fdmax; fcntl(stream_fs->fd, F_GETFL, &flags); fcntl(stream_fs->fd, F_SETFL, flags | O_NONBLOCK); FD_ZERO(&rdset); FD_SET(stream_fs->fd, &rdset); FD_SET(cancel_fd, &rdset); - select((stream_fs->fd+cancel_fd)/2+1, &rdset, 0, 0, NULL); + fdmax = MAX(stream_fs->fd, cancel_fd)+1; + select(fdmax, &rdset, 0, 0, NULL); if (FD_ISSET(cancel_fd, &rdset)) { fcntl(stream_fs->fd, F_SETFL, flags); errno = EINTR; @@ -277,6 +279,7 @@ stream_write (CamelStream *stream, const char *buffer, size_t n) } else { fd_set rdset, wrset; long flags; + int fdmax; fcntl(stream_fs->fd, F_GETFL, &flags); fcntl(stream_fs->fd, F_SETFL, flags | O_NONBLOCK); @@ -284,7 +287,8 @@ stream_write (CamelStream *stream, const char *buffer, size_t n) FD_ZERO(&wrset); FD_SET(stream_fs->fd, &wrset); FD_SET(cancel_fd, &rdset); - select((stream_fs->fd+cancel_fd)/2+1, &rdset, &wrset, 0, NULL); + fdmax = MAX(stream_fs->fd, cancel_fd)+1; + select(fdmax, &rdset, &wrset, 0, NULL); if (FD_ISSET(cancel_fd, &rdset)) { fcntl(stream_fs->fd, F_SETFL, flags); errno = EINTR; diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c index af61ed0981..db8cdd29dd 100644 --- a/camel/providers/imap/camel-imap-command.c +++ b/camel/providers/imap/camel-imap-command.c @@ -30,6 +30,7 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> +#include <errno.h> #include "camel-imap-command.h" #include "camel-imap-utils.h" @@ -283,6 +284,14 @@ imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex) str->str[0] = '\n'; nread = camel_stream_read (CAMEL_REMOTE_STORE (store)->istream, str->str + 1, length); + if (nread == -1) { + if (errno == EINTR) + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); + else + camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno)); + camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); + goto lose; + } if (nread < length) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Server response ended too soon.")); diff --git a/camel/providers/imap/camel-imap-private.h b/camel/providers/imap/camel-imap-private.h index 95ec3a5a0b..abcb3f8dd7 100644 --- a/camel/providers/imap/camel-imap-private.h +++ b/camel/providers/imap/camel-imap-private.h @@ -21,8 +21,8 @@ * USA */ -#ifndef CAMEL_PRIVATE_H -#define CAMEL_PRIVATE_H 1 +#ifndef CAMEL_IMAP_PRIVATE_H +#define CAMEL_IMAP_PRIVATE_H 1 #ifdef __cplusplus extern "C" { @@ -70,5 +70,5 @@ struct _CamelImapFolderPrivate { } #endif /* __cplusplus */ -#endif /* CAMEL_H */ +#endif /* CAMEL_IMAP_PRIVATE_H */ diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index ca4ca2e0d7..275270ecb6 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -48,6 +48,7 @@ #include "string-utils.h" #include "camel-imap-private.h" +#include "camel-private.h" #define d(x) x @@ -283,6 +284,31 @@ query_auth_types (CamelService *service, CamelException *ex) return g_list_prepend (types, &password_authtype); } +/* call refresh folder directly, bypassing the folder lock */ +static void +refresh_folder_info (gpointer key, gpointer value, gpointer data) +{ + CamelFolder *folder = CAMEL_FOLDER (value); + + CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, data); +} + +/* This is a little 'hack' to avoid the deadlock conditions that would otherwise + ensue when calling camel_folder_refresh_info from inside a lock */ +/* NB: on second thougts this is probably not entirely safe, but it'll do for now */ +/* the alternative is to: + make the camel folder->lock recursive (which should probably be done) + or remove it from camel_folder_refresh_info, and use another locking mechanism */ +static void +imap_store_refresh_folders (CamelRemoteStore *store, CamelException *ex) +{ + CAMEL_STORE_LOCK(store, cache_lock); + + g_hash_table_foreach (CAMEL_STORE (store)->folders, refresh_folder_info, ex); + + CAMEL_STORE_UNLOCK(store, cache_lock); +} + static gboolean imap_connect (CamelService *service, CamelException *ex) { @@ -476,7 +502,7 @@ imap_connect (CamelService *service, CamelException *ex) return FALSE; } - camel_remote_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex); + imap_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex); return !camel_exception_is_set (ex); } |