From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.devel Subject: Savannah down; Emacs trunk broken Date: Thu, 02 Jun 2011 09:40:10 -0700 Organization: UCLA Computer Science Department Message-ID: <4DE7BCEA.1030008@cs.ucla.edu> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1307033807 8437 80.91.229.12 (2 Jun 2011 16:56:47 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 2 Jun 2011 16:56:47 +0000 (UTC) To: Emacs-Devel devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jun 02 18:56:43 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QSBCL-00058l-Vo for ged-emacs-devel@m.gmane.org; Thu, 02 Jun 2011 18:56:42 +0200 Original-Received: from localhost ([::1]:47412 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSBCK-00063Z-Ur for ged-emacs-devel@m.gmane.org; Thu, 02 Jun 2011 12:56:41 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:37710) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSAwV-0001c3-DH for emacs-devel@gnu.org; Thu, 02 Jun 2011 12:40:21 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QSAwS-0003Hp-7A for emacs-devel@gnu.org; Thu, 02 Jun 2011 12:40:19 -0400 Original-Received: from smtp.cs.ucla.edu ([131.179.128.62]:36274) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSAwR-0003HR-A0 for emacs-devel@gnu.org; Thu, 02 Jun 2011 12:40:15 -0400 Original-Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp.cs.ucla.edu (Postfix) with ESMTP id 2FF2A39E80F7 for ; Thu, 2 Jun 2011 09:40:13 -0700 (PDT) X-Virus-Scanned: amavisd-new at smtp.cs.ucla.edu Original-Received: from smtp.cs.ucla.edu ([127.0.0.1]) by localhost (smtp.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8HIJ4Nwu6TXn for ; Thu, 2 Jun 2011 09:40:11 -0700 (PDT) Original-Received: from [131.179.64.200] (Penguin.CS.UCLA.EDU [131.179.64.200]) by smtp.cs.ucla.edu (Postfix) with ESMTPSA id 260A839E80F2 for ; Thu, 2 Jun 2011 09:40:11 -0700 (PDT) User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Thunderbird/3.1.10 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 131.179.128.62 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:140076 Archived-At: Last night I was committing some bug fixes to the Emacs trunk. I first separated out a gnulib merge that is needed for the bug fixes, built Emacs with just that, and committed it. I then prepared the rest of the fixes and was about to commit them, but had some glitches and was tired anyway, so I put it off until this morning. Unfortunately it turns out that Savannah is down, hard, with no public estimate for when it'll be back up. (Savannah has been unreliable lately, unfortunately.) Also, on further inspection although the gnulib changes *compile* with the latest Emacs, they can cause Emacs to crash if it runs out of memory, so they aren't compatible with Emacs at *runtime*. I will fix this as soon as I can after Savannah comes back up, but in the meantime, if you are using Emacs trunk bzr #104477 or later, and want an Emacs that doesn't go kaflooey when it runs out of memory, please use the following patch. I am rethinking the advisability of separating out the gnulib-related part of a patch before committing it. It takes extra work for me, and it can cause problems like this. I realize separating patches simplifies forensics later, but that benefit no longer seems like it's worth the hassle. # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: eggert@cs.ucla.edu-20110602084041-4nbcw6yh8wgazn6q # target_branch: bzr+ssh://eggert@bzr.savannah.gnu.org/emacs/trunk # testament_sha1: 75d67516fc39c4119a7b4927aca7bc29cc384223 # timestamp: 2011-06-02 09:14:46 -0700 # base_revision_id: eggert@cs.ucla.edu-20110602082257-mduuy7z1zlg0z8uo # # Begin patch === modified file 'src/ChangeLog' --- src/ChangeLog 2011-06-02 08:02:59 +0000 +++ src/ChangeLog 2011-06-02 08:40:41 +0000 @@ -1,5 +1,21 @@ 2011-06-02 Paul Eggert + Malloc failure behavior now depends on size of allocation. + * alloc.c (buffer_memory_full, memory_full): New arg NBYTES. + * lisp.h: Change signatures accordingly. + * alloc.c, buffer.c, editfns.c, menu.c, minibuf.c, xterm.c: + All callers changed. (Bug#8762) + + * gnutls.c: Use Emacs's memory allocators. + Without this change, the gnutls library would invoke malloc etc. + directly, which causes problems on non-SYNC_INPUT hosts, and which + runs afoul of improving memory_full behavior. (Bug#8761) + (fn_gnutls_global_set_mem_functions): New macro or function pointer. + (emacs_gnutls_global_init): Use it to specify xmalloc, xrealloc, + xfree instead of the default malloc, realloc, free. + (Fgnutls_boot): No need to check for memory allocation failure, + since xmalloc does that for us. + Remove arbitrary limit of 2**31 entries in hash tables. (Bug#8771) * category.c (hash_get_category_set): * ccl.c (ccl_driver): === modified file 'src/alloc.c' --- src/alloc.c 2011-05-31 06:05:00 +0000 +++ src/alloc.c 2011-06-02 08:35:28 +0000 @@ -467,7 +467,7 @@ /* Called if we can't allocate relocatable space for a buffer. */ void -buffer_memory_full (void) +buffer_memory_full (EMACS_INT nbytes) { /* If buffers use the relocating allocator, no need to free spare_memory, because we may have plenty of malloc space left @@ -477,7 +477,7 @@ malloc. */ #ifndef REL_ALLOC - memory_full (); + memory_full (nbytes); #endif /* This used to call error, but if we've run out of memory, we could @@ -673,7 +673,7 @@ MALLOC_UNBLOCK_INPUT; if (!val && size) - memory_full (); + memory_full (size); return val; } @@ -694,7 +694,8 @@ val = (POINTER_TYPE *) realloc (block, size); MALLOC_UNBLOCK_INPUT; - if (!val && size) memory_full (); + if (!val && size) + memory_full (size); return val; } @@ -787,7 +788,7 @@ MALLOC_UNBLOCK_INPUT; if (!val && nbytes) - memory_full (); + memory_full (nbytes); return val; } @@ -934,7 +935,7 @@ if (base == 0) { MALLOC_UNBLOCK_INPUT; - memory_full (); + memory_full (ABLOCKS_BYTES); } aligned = (base == abase); @@ -960,7 +961,7 @@ lisp_malloc_loser = base; free (base); MALLOC_UNBLOCK_INPUT; - memory_full (); + memory_full (SIZE_MAX); } } #endif @@ -2792,7 +2793,7 @@ int word_size = sizeof p->contents[0]; if ((SIZE_MAX - header_size) / word_size < len) - memory_full (); + memory_full (SIZE_MAX); MALLOC_BLOCK_INPUT; @@ -3270,35 +3271,58 @@ ************************************************************************/ -/* Called if malloc returns zero. */ +/* Called if malloc (NBYTES) returns zero. If NBYTES == SIZE_MAX, + there may have been size_t overflow so that malloc was never + called, or perhaps malloc was invoked successfully but the + resulting pointer had problems fitting into a tagged EMACS_INT. In + either case this counts as memory being full even though malloc did + not fail. */ void -memory_full (void) +memory_full (size_t nbytes) { - int i; - - Vmemory_full = Qt; - - memory_full_cons_threshold = sizeof (struct cons_block); - - /* The first time we get here, free the spare memory. */ - for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) - if (spare_memory[i]) - { - if (i == 0) - free (spare_memory[i]); - else if (i >= 1 && i <= 4) - lisp_align_free (spare_memory[i]); - else - lisp_free (spare_memory[i]); - spare_memory[i] = 0; - } - - /* Record the space now used. When it decreases substantially, - we can refill the memory reserve. */ + /* Do not go into hysterics merely because a large request failed. */ + int enough_free_memory = 0; + if (SPARE_MEMORY < nbytes) + { + void *p = malloc (SPARE_MEMORY); + if (p) + { + if (spare_memory[0]) + free (p); + else + spare_memory[0] = p; + enough_free_memory = 1; + } + } + + if (! enough_free_memory) + { + int i; + + Vmemory_full = Qt; + + memory_full_cons_threshold = sizeof (struct cons_block); + + /* The first time we get here, free the spare memory. */ + for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) + if (spare_memory[i]) + { + if (i == 0) + free (spare_memory[i]); + else if (i >= 1 && i <= 4) + lisp_align_free (spare_memory[i]); + else + lisp_free (spare_memory[i]); + spare_memory[i] = 0; + } + + /* Record the space now used. When it decreases substantially, + we can refill the memory reserve. */ #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT - bytes_used_when_full = BYTES_USED; + bytes_used_when_full = BYTES_USED; #endif + } /* This used to call error, but if we've run out of memory, we could get infinite recursion trying to build the string. */ === modified file 'src/buffer.c' --- src/buffer.c 2011-05-12 07:07:06 +0000 +++ src/buffer.c 2011-05-30 16:47:35 +0000 @@ -328,7 +328,7 @@ alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1); UNBLOCK_INPUT; if (! BUF_BEG_ADDR (b)) - buffer_memory_full (); + buffer_memory_full (BUF_GAP_SIZE (b) + 1); b->pt = BEG; b->begv = BEG; @@ -4892,7 +4892,7 @@ if (p == NULL) { UNBLOCK_INPUT; - memory_full (); + memory_full (nbytes); } b->text->beg = (unsigned char *) p; @@ -4920,7 +4920,7 @@ if (p == NULL) { UNBLOCK_INPUT; - memory_full (); + memory_full (nbytes); } BUF_BEG_ADDR (b) = (unsigned char *) p; === modified file 'src/editfns.c' --- src/editfns.c 2011-05-27 19:37:32 +0000 +++ src/editfns.c 2011-05-30 16:47:35 +0000 @@ -3636,7 +3636,7 @@ { EMACS_INT i; if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs) - memory_full (); + memory_full (SIZE_MAX); SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen); discarded = (char *) &info[nargs + 1]; for (i = 0; i < nargs + 1; i++) === modified file 'src/gnutls.c' --- src/gnutls.c 2011-05-23 00:03:40 +0000 +++ src/gnutls.c 2011-05-30 08:03:15 +0000 @@ -110,6 +110,10 @@ DEF_GNUTLS_FN (int, gnutls_global_init, (void)); DEF_GNUTLS_FN (void, gnutls_global_set_log_function, (gnutls_log_func)); DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int)); +DEF_GNUTLS_FN (void, gnutls_global_set_mem_functions, + (gnutls_alloc_function, gnutls_alloc_function, + gnutls_is_secure_function, gnutls_realloc_function, + gnutls_free_function)); DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t)); DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, gnutls_connection_end_t)); DEF_GNUTLS_FN (int, gnutls_priority_set_direct, @@ -168,6 +172,7 @@ LOAD_GNUTLS_FN (library, gnutls_global_init); LOAD_GNUTLS_FN (library, gnutls_global_set_log_function); LOAD_GNUTLS_FN (library, gnutls_global_set_log_level); + LOAD_GNUTLS_FN (library, gnutls_global_set_mem_functions); LOAD_GNUTLS_FN (library, gnutls_handshake); LOAD_GNUTLS_FN (library, gnutls_init); LOAD_GNUTLS_FN (library, gnutls_priority_set_direct); @@ -213,6 +218,7 @@ #define fn_gnutls_global_init gnutls_global_init #define fn_gnutls_global_set_log_function gnutls_global_set_log_function #define fn_gnutls_global_set_log_level gnutls_global_set_log_level +#define fn_gnutls_global_set_mem_functions gnutls_global_set_mem_functions #define fn_gnutls_handshake gnutls_handshake #define fn_gnutls_init gnutls_init #define fn_gnutls_priority_set_direct gnutls_priority_set_direct @@ -582,7 +588,11 @@ int ret = GNUTLS_E_SUCCESS; if (!gnutls_global_initialized) - ret = fn_gnutls_global_init (); + { + fn_gnutls_global_set_mem_functions (xmalloc, xmalloc, NULL, + xrealloc, xfree); + ret = fn_gnutls_global_init (); + } gnutls_global_initialized = 1; return gnutls_make_error (ret); @@ -768,8 +778,7 @@ { GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); x509_cred = XPROCESS (proc)->gnutls_x509_cred; - if (fn_gnutls_certificate_allocate_credentials (&x509_cred) < 0) - memory_full (); + fn_gnutls_certificate_allocate_credentials (&x509_cred); if (NUMBERP (verify_flags)) { @@ -792,8 +801,7 @@ { GNUTLS_LOG (2, max_log_level, "allocating anon credentials"); anon_cred = XPROCESS (proc)->gnutls_anon_cred; - if (fn_gnutls_anon_allocate_client_credentials (&anon_cred) < 0) - memory_full (); + fn_gnutls_anon_allocate_client_credentials (&anon_cred); } else { === modified file 'src/lisp.h' --- src/lisp.h 2011-05-31 06:05:00 +0000 +++ src/lisp.h 2011-06-02 08:25:28 +0000 @@ -2684,8 +2684,8 @@ extern void reset_malloc_hooks (void); extern void uninterrupt_malloc (void); extern void malloc_warning (const char *); -extern void memory_full (void) NO_RETURN; -extern void buffer_memory_full (void) NO_RETURN; +extern void memory_full (size_t) NO_RETURN; +extern void buffer_memory_full (EMACS_INT) NO_RETURN; extern int survives_gc_p (Lisp_Object); extern void mark_object (Lisp_Object); #if defined REL_ALLOC && !defined SYSTEM_MALLOC === modified file 'src/menu.c' --- src/menu.c 2011-05-18 03:03:15 +0000 +++ src/menu.c 2011-05-30 16:47:35 +0000 @@ -178,7 +178,7 @@ grow_menu_items (void) { if ((INT_MAX - MENU_ITEMS_PANE_LENGTH) / 2 < menu_items_allocated) - memory_full (); + memory_full (SIZE_MAX); menu_items_allocated *= 2; menu_items = larger_vector (menu_items, menu_items_allocated, Qnil); } === modified file 'src/minibuf.c' --- src/minibuf.c 2011-06-02 07:42:55 +0000 +++ src/minibuf.c 2011-06-02 08:25:28 +0000 @@ -245,7 +245,7 @@ len == size - 1 && line[len - 1] != '\n')) { if ((size_t) -1 / 2 < size) - memory_full (); + memory_full (SIZE_MAX); size *= 2; line = (char *) xrealloc (line, size); } === modified file 'src/xterm.c' --- src/xterm.c 2011-05-28 22:39:39 +0000 +++ src/xterm.c 2011-05-31 05:45:07 +0000 @@ -4225,7 +4225,7 @@ size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows; if ((size_t) -1 / sizeof *scroll_bar_windows < new_size) - memory_full (); + memory_full (SIZE_MAX); scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows, nbytes); memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes); # Begin bundle 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 4v6zSlBN/8XckU4UJCwiKUyA