diff --git a/NEWS b/NEWS index 87e6590c8..65406688e 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,14 @@ You can see the complete list of recent changes, bugfixes and new features in the http://repo.or.cz/w/elinks.git[gitweb interface]. See the ChangeLog file for details. +ELinks 0.11.5.GIT now: +---------------------- + +To be released as 0.11.6. + +* critical bug 1053: fix crash if a download finishes after ELinks has + closed the terminal from which the download was started + ELinks 0.11.5: -------------- diff --git a/src/session/download.c b/src/session/download.c index a34a6f829..afce521de 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -220,6 +220,29 @@ destroy_downloads(struct session *ses) } } +void +detach_downloads_from_terminal(struct terminal *term) +{ + struct file_download *file_download, *next; + + assert(term != NULL); + if_assert_failed return; + + foreachsafe (file_download, next, downloads) { + if (file_download->term != term) + continue; + + if (!file_download->external_handler) { + file_download->term = NULL; + if (file_download->ses + && file_download->ses->tab->term == term) + file_download->ses = NULL; + continue; + } + + abort_download(file_download); + } +} static void download_error_dialog(struct file_download *file_download, int saved_errno) @@ -307,6 +330,9 @@ download_data_store(struct download *download, struct file_download *file_downlo { struct terminal *term = file_download->term; + assert_terminal_ptr_not_dangling(term); + if_assert_failed term = file_download->term = NULL; + if (!term) { /* No term here, so no beep. --Zas */ abort_download(file_download); diff --git a/src/session/download.h b/src/session/download.h index 1bcc4aadf..b27cd3b78 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -107,6 +107,7 @@ void create_download_file(struct terminal *, unsigned char *, unsigned char **, void abort_all_downloads(void); void destroy_downloads(struct session *); +void detach_downloads_from_terminal(struct terminal *); int setup_download_handler(struct session *, struct download *, struct cache_entry *, int); diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 895e89806..b22158223 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -115,6 +115,7 @@ destroy_terminal(struct terminal *term) #ifdef CONFIG_BOOKMARKS bookmark_auto_save_tabs(term); #endif + detach_downloads_from_terminal(term); while (!list_empty(term->windows)) delete_window(term->windows.next); @@ -197,6 +198,24 @@ unblock_terminal(struct terminal *term) textarea_edit(1, NULL, NULL, NULL, NULL); } +#ifndef CONFIG_FASTMEM +void +assert_terminal_ptr_not_dangling(const struct terminal *suspect) +{ + struct terminal *term; + + if (suspect == NULL) + return; + + foreach (term, terminals) { + if (term == suspect) + return; + } + + assertm(0, "Dangling pointer to struct terminal"); +} +#endif /* !CONFIG_FASTMEM */ + void exec_on_terminal(struct terminal *term, unsigned char *path, unsigned char *delete, int fg) diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index 0689f098e..8b44ff1a9 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -150,6 +150,12 @@ void destroy_all_terminals(void); void exec_thread(unsigned char *, int); void close_handle(void *); +#ifdef CONFIG_FASTMEM +#define assert_terminal_ptr_not_dangling(suspect) ((void) 0) +#else /* assert() does something */ +void assert_terminal_ptr_not_dangling(const struct terminal *); +#endif + #define TERM_FN_TITLE 1 #define TERM_FN_RESIZE 2