aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog5
-rw-r--r--mail/mail-format.c3
-rw-r--r--mail/message-thread.c201
3 files changed, 179 insertions, 30 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 516b9ea488..88bbb72541 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,7 +1,10 @@
2000-08-16 Peter Williams <peterw@helixcode.com>
* message-thread.c (walk_containers): More (default disabled)
- mem debugging here.
+ mem debugging here. Fix the big leaks.
+
+ * mail-format.c (get_url_for_icon): Copy the url_path so that
+ it can't get freed under us.
2000-08-15 Peter Williams <peterw@helixcode.com>
diff --git a/mail/mail-format.c b/mail/mail-format.c
index f9739b911e..a73d2faf89 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -216,7 +216,8 @@ get_url_for_icon (const char *icon_name, MailDisplay *md)
}
close (fd);
- g_hash_table_insert (icons, icon_path, ba);
+ /* FIXME: these aren't freed. */
+ g_hash_table_insert (icons, g_strdup (icon_path), ba);
}
g_free (icon_path);
diff --git a/mail/message-thread.c b/mail/message-thread.c
index 34a6456015..c8ed152e71 100644
--- a/mail/message-thread.c
+++ b/mail/message-thread.c
@@ -47,12 +47,18 @@ static GHashTable *allocedht = NULL;
#define EXISTS (1 << 0)
#define WALKED (1 << 1)
#define FREED (1 << 2)
+#define AL_401 (1 << 3)
+#define AL_541 (1 << 4)
+#define AL_546 (1 << 5)
+#define AL_569 (1 << 6)
+#define LINKED (1 << 7)
+#define EXCUSED (1 << 8)
#define GITP(x) GINT_TO_POINTER(x)
#define GPTI(x) GPOINTER_TO_INT(x)
static struct _container *
-alloc_container (void)
+alloc_container (int where)
{
struct _container *c;
@@ -61,17 +67,19 @@ alloc_container (void)
if (!allocedht)
allocedht = g_hash_table_new (g_direct_hash, g_direct_equal);
- g_hash_table_insert (allocedht, c, GITP(EXISTS));
+ g_hash_table_insert (allocedht, c, GITP(EXISTS|where));
return c;
}
static void
free_container (struct _container **c)
{
+ gpointer flags;
+
memset ((*c), 0, sizeof (struct _container));
- if (g_hash_table_lookup (allocedht, c) == NULL)
+ if ((flags = g_hash_table_lookup (allocedht, (*c))) == NULL)
printf ("** threading mem debug: freeing unalloced entry %p?\n", (*c));
- g_hash_table_insert (allocedht, c, GITP(EXISTS|FREED));
+ g_hash_table_insert (allocedht, (*c), GITP(GPTI(flags)|FREED));
g_free ((*c));
(*c) = NULL;
}
@@ -80,21 +88,117 @@ static void
cont_print (gpointer key, gpointer value, gpointer user)
{
struct _container *c = (struct _container *) key;
+ char *line;
+
+ if (GPTI(value) & FREED)
+ return;
- printf (" %p: %p %p %p %s %s %d %d : %s %s\n",
+ if (GPTI(value) & AL_401)
+ line = "401";
+ else if (GPTI(value) & AL_541)
+ line = "541";
+ else if (GPTI(value) & AL_546)
+ line = "546";
+ else if (GPTI(value) & AL_569)
+ line = "569";
+ else
+ line = "???";
+
+ printf (" %p : %s %s %s %s %s",
c,
- c->next, c->parent, c->child,
- c->message ? c->message->subject : "(null message)",
- c->root_subject ? c->root_subject : "(null root-subject)",
- c->re, c->order,
+ GPTI(value) & FREED ? "freed" : "unfrd",
GPTI(value) & WALKED ? "walked" : "unwlkd",
- GPTI(value) & FREED ? "freed" : "unfrd");
+ line,
+ GPTI(value) & LINKED ? "linked" : "unlnkd",
+ GPTI(value) & EXCUSED ? "excused" : "unexcsd");
+
+ if ((GPTI(value) & FREED) == 0) {
+ gpointer oth_flags;
+
+ printf (" : %p %p %p : \"%s\" \"%s\" %d %d",
+ c->next, c->parent, c->child,
+ c->message ? c->message->subject : "(null message)",
+ c->root_subject ? c->root_subject : "(null root-subject)",
+ c->re, c->order);
+
+ if (c->next) {
+ oth_flags = g_hash_table_lookup (allocedht, c->next);
+
+ printf ("\n next : %p : %s %s %s",
+ c->next,
+ GPTI(oth_flags) & WALKED ? "walked" : "unwlkd",
+ GPTI(oth_flags) & LINKED ? "linked" : "unlnkd",
+ GPTI(oth_flags) & EXCUSED ? "excused" : "unexcsd");
+ }
+
+ if (c->parent) {
+ oth_flags = g_hash_table_lookup (allocedht, c->parent);
+
+ printf ("\n prnt : %p : %s %s %s",
+ c->parent,
+ GPTI(oth_flags) & WALKED ? "walked" : "unwlkd",
+ GPTI(oth_flags) & LINKED ? "linked" : "unlnkd",
+ GPTI(oth_flags) & EXCUSED ? "excused" : "unexcsd");
+ }
+
+ if (c->child) {
+ oth_flags = g_hash_table_lookup (allocedht, c->child);
+
+ printf ("\n chld : %p : %s %s %s",
+ c->child,
+ GPTI(oth_flags) & WALKED ? "walked" : "unwlkd",
+ GPTI(oth_flags) & LINKED ? "linked" : "unlnkd",
+ GPTI(oth_flags) & EXCUSED ? "excused" : "unexcsd");
+ }
+
+ }
+
+ printf ("\n");
+
+}
+
+static void
+make_excuses (gpointer key, gpointer value, gpointer user)
+{
+ struct _container *c;
+ gpointer chldflags;
+ gpointer nextflags;
+
+ if (GPTI(value) & FREED)
+ return;
+
+ c = (struct _container *) key;
+
+ if (c->next) {
+ nextflags = g_hash_table_lookup (allocedht, c->next);
+
+ if ((GPTI(nextflags) & EXCUSED) == 0) {
+ g_hash_table_insert (allocedht, c->next, GITP(GPTI(nextflags)|EXCUSED));
+ ((gint *)user) = 1;
+ }
+ }
+
+ if (c->child) {
+ chldflags = g_hash_table_lookup (allocedht, c->child);
+
+ if ((GPTI(chldflags) & EXCUSED) == 0) {
+ g_hash_table_insert (allocedht, c->child, GITP(GPTI(chldflags)|EXCUSED));
+ ((gint *)user) = 1;
+ }
+ }
}
static void
print_containers (void)
{
- printf ("Containers currently unfreed:\n");
+ gint hit;
+
+ do {
+ hit = 0;
+ g_hash_table_foreach (allocedht, make_excuses, &hit);
+ } while (hit);
+
+ printf ("List of container stats:\n");
g_hash_table_foreach (allocedht, cont_print, NULL);
printf ("End of list.\n");
}
@@ -117,11 +221,22 @@ walk_containers (struct _container *head)
}
}
+static void
+link_container (struct _container *c)
+{
+ gpointer flags;
+
+ if ((flags = g_hash_table_lookup (allocedht, c)) == NULL)
+ printf ("** threading mem debug: linking unalloced entry %p?\n", c);
+ g_hash_table_insert (allocedht, c, GITP(GPTI(flags)|LINKED));
+}
+
#else
-#define alloc_container() (g_new0 (struct _container, 1))
+#define alloc_container(w) (g_new0 (struct _container, 1))
#define free_container(c) g_free (*(c))
#define print_containers()
#define walk_containers(c)
+#define link_container(c)
#endif
/* **************************************** */
@@ -174,7 +289,7 @@ container_unparent_child(struct _container *child)
static void
container_parent_child(struct _container *parent, struct _container *child)
{
- struct _container *c, *node;
+ struct _container *c, *node, **prev;
/* are we already the right parent? */
if (child->parent == parent)
@@ -186,19 +301,48 @@ container_parent_child(struct _container *parent, struct _container *child)
return;
}
+ /* check for trying to make my child my parent */
+ for (c = parent; c; c = c->parent) {
+ if (c == child) {
+ d(printf("AIIE: trying to lop off hunk of nodes!\n"));
+ return;
+ }
+ }
+
/* else remove child from its existing parent, and reparent */
node = child->parent;
- c = (struct _container *)&node->child;
- d(printf("scanning children:\n"));
- while (c->next) {
- d(printf(" %p\n", c));
- if (c->next==child) {
- d(printf("found node %p\n", child));
- c->next = c->next->next;
- child->parent = NULL;
- container_add_child(parent, child);
+
+ /* c = (struct _container *)&node->child;
+ *d(printf("scanning children:\n"));
+ *while (c->next) {
+ * d(printf(" %p\n", c));
+ * if (c->next==child) {
+ * d(printf("found node %p\n", child));
+ * c->next = c->next->next;
+ * child->parent = NULL;
+ * container_add_child(parent, child);
+ * return;
+ * }
+ * c = c->next;
+ *}
+ */
+
+ d(printf("PKGW deparent child"));
+ c = node->child;
+ prev = &(node->child);
+ while (c) {
+ d(printf (" %p\n", c));
+
+ if (c == child) {
+ d(printf (" hit child %p\n", child));
+ (*prev) = c->next;
+ c->next = NULL;
+ c->parent = NULL;
+ container_add_child (parent, child);
return;
}
+
+ prev = &(c->next);
c = c->next;
}
@@ -221,6 +365,7 @@ prune_empty(struct _container **cp)
if (c->child == NULL) {
d(printf("removing empty node\n"));
lastc->next = c->next;
+ free_container (&c);
continue;
}
if (c->parent || c->child->next==0) {
@@ -236,6 +381,7 @@ prune_empty(struct _container **cp)
child = next;
}
+ free_container (&c);
continue;
}
}
@@ -253,6 +399,7 @@ hashloop(void *key, void *value, void *data)
if (c->parent == NULL) {
c->next = tail->next;
tail->next = c;
+ link_container(c);
}
}
@@ -386,7 +533,7 @@ group_root_set(struct _container **cp)
remove_node(cp, container, &clast);
remove_node(cp, c, &clast);
- scan = alloc_container();
+ scan = alloc_container(AL_401);
scan->root_subject = c->root_subject;
scan->re = c->re && container->re;
scan->next = c->next;
@@ -431,8 +578,6 @@ static void thread_messages_free(struct _container *c)
{
struct _container *n;
- return;
-
/* FIXME: ok, for some reason this doesn't work .. investigate later ... */
while (c) {
@@ -528,12 +673,12 @@ thread_messages(CamelFolder *folder, GPtrArray *uids)
d(printf("doing : %s\n", mi->message_id));
c = g_hash_table_lookup(id_table, mi->message_id);
if (!c) {
- c = alloc_container();
+ c = alloc_container(AL_541);
g_hash_table_insert(id_table, mi->message_id, c);
}
} else {
d(printf("doing : (no message id)\n"));
- c = alloc_container();
+ c = alloc_container(AL_546);
g_hash_table_insert(no_id_table, (void *)mi, c);
}
@@ -556,7 +701,7 @@ thread_messages(CamelFolder *folder, GPtrArray *uids)
c = g_hash_table_lookup(id_table, ref->id);
if (c == NULL) {
d(printf("not found\n"));
- c = alloc_container();
+ c = alloc_container(AL_569);
g_hash_table_insert(id_table, ref->id, c);
}
if (c!=child)