diff --git a/src/cookies/cookies.c b/src/cookies/cookies.c index 9fe3c5e2..4e20e74d 100644 --- a/src/cookies/cookies.c +++ b/src/cookies/cookies.c @@ -29,6 +29,7 @@ #include "intl/gettext/libintl.h" #include "main/module.h" #include "main/object.h" +#include "main/select.h" #include "protocol/date.h" #include "protocol/header.h" #include "protocol/protocol.h" @@ -69,6 +70,7 @@ static INIT_LIST_HEAD(c_domains); * struct cookie_server. */ static INIT_LIST_HEAD(cookie_servers); +/* Only @set_cookies_dirty may make this nonzero. */ static int cookies_dirty = 0; enum cookies_option { @@ -506,7 +508,7 @@ accept_cookie(struct cookie *cookie) } add_to_list(cookies, cookie); - cookies_dirty = 1; + set_cookies_dirty(); /* XXX: This crunches CPU too. --pasky */ foreach (cd, c_domains) @@ -520,9 +522,6 @@ accept_cookie(struct cookie *cookie) memcpy(cd->domain, cookie->domain, domain_len + 1); add_to_list(c_domains, cd); - - if (get_cookies_save() && get_cookies_resave()) - save_cookies(); } #if 0 @@ -549,9 +548,6 @@ delete_cookie(struct cookie *c) end: del_from_list(c); done_cookie(c); - - if (get_cookies_save() && get_cookies_resave()) - save_cookies(); } @@ -679,7 +675,7 @@ send_cookies(struct uri *uri) #endif delete_cookie(c); - cookies_dirty = 1; + set_cookies_dirty(); continue; } @@ -700,9 +696,6 @@ send_cookies(struct uri *uri) mem_free(path); - if (cookies_dirty && get_cookies_save() && get_cookies_resave()) - save_cookies(); - if (!header.length) { done_string(&header); return NULL; @@ -772,7 +765,7 @@ load_cookies(void) { /* Skip expired cookies if any. */ expires = str_to_time_t(members[EXPIRES].pos); if (!expires || expires <= now) { - cookies_dirty = 1; + set_cookies_dirty(); continue; } @@ -803,6 +796,30 @@ load_cookies(void) { fclose(fp); } +static void +resave_cookies_bottom_half(void *always_null) +{ + if (get_cookies_save() && get_cookies_resave()) + save_cookies(); /* checks cookies_dirty */ +} + +/* Note that the cookies have been modified, and register a bottom + * half for saving them if appropriate. We use a bottom half so that + * if something makes multiple changes and calls this for each change, + * the cookies get saved only once at the end. */ +void +set_cookies_dirty(void) +{ + /* Do not check @cookies_dirty here. If the previous attempt + * to save cookies failed, @cookies_dirty can still be nonzero + * even though @resave_cookies_bottom_half is no longer in the + * queue. */ + cookies_dirty = 1; + /* If @resave_cookies_bottom_half is already in the queue, + * @register_bottom_half does nothing. */ + register_bottom_half(resave_cookies_bottom_half, NULL); +} + void save_cookies(void) { struct cookie *c; diff --git a/src/cookies/cookies.h b/src/cookies/cookies.h index db2f01ce..be60ae26 100644 --- a/src/cookies/cookies.h +++ b/src/cookies/cookies.h @@ -45,6 +45,7 @@ void delete_cookie(struct cookie *); void set_cookie(struct uri *, unsigned char *); void load_cookies(void); void save_cookies(void); +void set_cookies_dirty(void); /* Note that the returned value points to a static structure and thus the * string will be overwritten at the next call time. The string source