changeset 58818:f8cddae7d959

* gtkutil.c: Include signal.h and syssignal.h. (xg_get_file_name): Block and unblock __SIGRTMIN if defined. * alloc.c: If HAVE_GTK_AND_PTHREAD, include pthread.h, new variables main_thread and alloc_mutex, define (UN)BLOCK_INPUT_ALLOC to use alloc_mutex to protect emacs_blocked_* calls and only do (UN)BLOCK_INPUT in the main thread. If not HAVE_GTK_AND_PTHREAD, (UN)BLOCK_INPUT_ALLOC is the same as (UN)BLOCK_INPUT. (emacs_blocked_free, emacs_blocked_malloc) (emacs_blocked_realloc): Use (UN)BLOCK_INPUT_ALLOC. (uninterrupt_malloc): Initialize main_thread and alloc_mutex. (reset_malloc_hooks): New function. * lisp.h: Declare reset_malloc_hooks. * emacs.c (Fdump_emacs): Call reset_malloc_hooks. * keyboard.c: Conditionally include pthread.h (handle_async_inpu, input_available_signalt): If not in the main thread, block signal, send signal to main thread and return.
author Jan Djärv <jan.h.d@swipnet.se>
date Tue, 07 Dec 2004 08:25:43 +0000
parents 65f1b18b7f66
children 856c9ea2409a
files src/ChangeLog src/alloc.c src/emacs.c src/gtkutil.c src/keyboard.c src/lisp.h
diffstat 6 files changed, 147 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/ChangeLog	Tue Dec 07 08:25:43 2004 +0000
@@ -1,5 +1,27 @@
 2004-12-07  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
 
+	* gtkutil.c: Include signal.h and syssignal.h.
+	(xg_get_file_name): Block and unblock __SIGRTMIN if defined.
+
+	* alloc.c: If HAVE_GTK_AND_PTHREAD, include pthread.h,
+	new variables main_thread and alloc_mutex,
+	define (UN)BLOCK_INPUT_ALLOC to use alloc_mutex to protect
+	emacs_blocked_* calls and only do (UN)BLOCK_INPUT in the main thread.
+	If not HAVE_GTK_AND_PTHREAD, (UN)BLOCK_INPUT_ALLOC is the same as
+	(UN)BLOCK_INPUT.
+	(emacs_blocked_free, emacs_blocked_malloc)
+	(emacs_blocked_realloc): Use (UN)BLOCK_INPUT_ALLOC.
+	(uninterrupt_malloc): Initialize main_thread and alloc_mutex.
+	(reset_malloc_hooks): New function.
+
+	* lisp.h: Declare reset_malloc_hooks.
+
+	* emacs.c (Fdump_emacs): Call reset_malloc_hooks.
+
+	* keyboard.c: Conditionally include pthread.h
+	(handle_async_inpu, input_available_signalt): If not in the main
+	thread, block signal, send signal to main thread and return.
+
 	* gtkutil.c (xg_get_file_with_chooser): Handle local files only.
 	Set current folder in file chooser if default_filename is a
 	directory.
--- a/src/alloc.c	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/alloc.c	Tue Dec 07 08:25:43 2004 +0000
@@ -31,6 +31,10 @@
 
 #include <signal.h>
 
+#ifdef HAVE_GTK_AND_PTHREAD
+#include <pthread.h>
+#endif
+
 /* This file is part of the core Lisp implementation, and thus must
    deal with the real data structures.  If the Lisp implementation is
    replaced, this file likely will not be used.  */
@@ -85,6 +89,35 @@
 
 #endif /* not DOUG_LEA_MALLOC */
 
+#if ! defined (SYSTEM_MALLOC) && defined (HAVE_GTK_AND_PTHREAD)
+
+static pthread_mutex_t alloc_mutex;
+pthread_t main_thread;
+
+#define BLOCK_INPUT_ALLOC                       \
+  do                                            \
+    {                                           \
+      pthread_mutex_lock (&alloc_mutex);        \
+      if (pthread_self () == main_thread)       \
+        BLOCK_INPUT;                            \
+    }                                           \
+  while (0)
+#define UNBLOCK_INPUT_ALLOC                     \
+  do                                            \
+    {                                           \
+      if (pthread_self () == main_thread)       \
+        UNBLOCK_INPUT;                          \
+      pthread_mutex_unlock (&alloc_mutex);      \
+    }                                           \
+  while (0)
+
+#else /* SYSTEM_MALLOC || not HAVE_GTK_AND_PTHREAD */
+
+#define BLOCK_INPUT_ALLOC BLOCK_INPUT
+#define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT
+
+#endif /* SYSTEM_MALLOC || not HAVE_GTK_AND_PTHREAD */
+
 /* Value of _bytes_used, when spare_memory was freed.  */
 
 static __malloc_size_t bytes_used_when_full;
@@ -1068,7 +1101,7 @@
 emacs_blocked_free (ptr)
      void *ptr;
 {
-  BLOCK_INPUT;
+  BLOCK_INPUT_ALLOC;
 
 #ifdef GC_MALLOC_CHECK
   if (ptr)
@@ -1106,7 +1139,7 @@
     spare_memory = (char *) malloc ((size_t) SPARE_MEMORY);
 
   __free_hook = emacs_blocked_free;
-  UNBLOCK_INPUT;
+  UNBLOCK_INPUT_ALLOC;
 }
 
 
@@ -1132,7 +1165,7 @@
 {
   void *value;
 
-  BLOCK_INPUT;
+  BLOCK_INPUT_ALLOC;
   __malloc_hook = old_malloc_hook;
 #ifdef DOUG_LEA_MALLOC
     mallopt (M_TOP_PAD, malloc_hysteresis * 4096);
@@ -1164,7 +1197,7 @@
 #endif /* GC_MALLOC_CHECK */
 
   __malloc_hook = emacs_blocked_malloc;
-  UNBLOCK_INPUT;
+  UNBLOCK_INPUT_ALLOC;
 
   /* fprintf (stderr, "%p malloc\n", value); */
   return value;
@@ -1180,7 +1213,7 @@
 {
   void *value;
 
-  BLOCK_INPUT;
+  BLOCK_INPUT_ALLOC;
   __realloc_hook = old_realloc_hook;
 
 #ifdef GC_MALLOC_CHECK
@@ -1225,17 +1258,45 @@
 #endif /* GC_MALLOC_CHECK */
 
   __realloc_hook = emacs_blocked_realloc;
-  UNBLOCK_INPUT;
+  UNBLOCK_INPUT_ALLOC;
 
   return value;
 }
 
 
+#ifdef HAVE_GTK_AND_PTHREAD
+/* Called from Fdump_emacs so that when the dumped Emacs starts, it has a
+   normal malloc.  Some thread implementations need this as they call
+   malloc before main.  The pthread_self call in BLOCK_INPUT_ALLOC then
+   calls malloc because it is the first call, and we have an endless loop.  */
+
+void
+reset_malloc_hooks ()
+{
+  __free_hook = 0;
+  __malloc_hook = 0;
+  __realloc_hook = 0;
+}
+#endif /* HAVE_GTK_AND_PTHREAD */
+
+
 /* Called from main to set up malloc to use our hooks.  */
 
 void
 uninterrupt_malloc ()
 {
+#ifdef HAVE_GTK_AND_PTHREAD
+  pthread_mutexattr_t attr;
+
+  /*  GLIBC has a faster way to do this, but lets keep it portable.
+      This is according to the Single UNIX Specification.  */
+  pthread_mutexattr_init (&attr);
+  pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init (&alloc_mutex, &attr);
+
+  main_thread = pthread_self ();
+#endif /* HAVE_GTK_AND_PTHREAD */
+
   if (__free_hook != emacs_blocked_free)
     old_free_hook = __free_hook;
   __free_hook = emacs_blocked_free;
--- a/src/emacs.c	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/emacs.c	Tue Dec 07 08:25:43 2004 +0000
@@ -2238,6 +2238,12 @@
   memory_warnings (my_edata, malloc_warning);
 #endif /* not WINDOWSNT */
 #endif
+#ifdef HAVE_GTK_AND_PTHREAD
+  /* Pthread may call malloc before main, and then we will get an endless
+     loop, because pthread_self (see alloc.c) calls malloc the first time
+     it is called on some systems.  */
+  reset_malloc_hooks ();
+#endif
 #ifdef DOUG_LEA_MALLOC
   malloc_state_ptr = malloc_get_state ();
 #endif
--- a/src/gtkutil.c	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/gtkutil.c	Tue Dec 07 08:25:43 2004 +0000
@@ -23,10 +23,12 @@
 
 #ifdef USE_GTK
 #include <string.h>
+#include <signal.h>
 #include <stdio.h>
 #include "lisp.h"
 #include "xterm.h"
 #include "blockinput.h"
+#include "syssignal.h"
 #include "window.h"
 #include "atimer.h"
 #include "gtkutil.h"
@@ -1311,6 +1313,13 @@
   int filesel_done = 0;
   xg_get_file_func func;
 
+#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
+  /* I really don't know why this is needed, but without this the GLIBC add on
+     library linuxthreads hangs when the Gnome file chooser backend creates
+     threads.  */
+  sigblock (sigmask (__SIGRTMIN));
+#endif /* HAVE_GTK_AND_PTHREAD */
+
 #ifdef HAVE_GTK_FILE_BOTH
   extern int x_use_old_gtk_file_dialog;
 
@@ -1358,6 +1367,10 @@
       gtk_main_iteration ();
     }
 
+#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
+  sigunblock (sigmask (__SIGRTMIN));
+#endif
+
   if (filesel_done == GTK_RESPONSE_OK)
     fn = (*func) (w);
 
--- a/src/keyboard.c	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/keyboard.c	Tue Dec 07 08:25:43 2004 +0000
@@ -45,6 +45,9 @@
 #include <setjmp.h>
 #include <errno.h>
 
+#ifdef HAVE_GTK_AND_PTHREAD
+#include <pthread.h>
+#endif
 #ifdef MSDOS
 #include "msdos.h"
 #include <time.h>
@@ -6777,6 +6780,25 @@
 #ifdef BSD4_1
   extern int select_alarmed;
 #endif
+#ifdef HAVE_GTK_AND_PTHREAD
+  extern pthread_t main_thread;
+  if (pthread_self () != main_thread)
+    {
+      /* POSIX says any thread can receive the signal.  On GNU/Linux that is
+         not true, but for other systems (FreeBSD at least) it is.  So direct
+         the signal to the correct thread and block it from this thread.  */
+#ifdef SIGIO
+      sigset_t new_mask;
+
+      sigemptyset (&new_mask);
+      sigaddset (&new_mask, SIGIO);
+      pthread_sigmask (SIG_BLOCK, &new_mask, 0);
+      pthread_kill (main_thread, SIGIO);
+#endif
+      return;
+    }
+#endif
+
   interrupt_input_pending = 0;
 
   while (1)
@@ -6804,7 +6826,22 @@
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-
+#ifdef HAVE_GTK_AND_PTHREAD
+  extern pthread_t main_thread;
+  if (pthread_self () != main_thread)
+    {
+      /* POSIX says any thread can receive the signal.  On GNU/Linux that is
+         not true, but for other systems (FreeBSD at least) it is.  So direct
+         the signal to the correct thread and block it from this thread.  */
+      sigset_t new_mask;
+
+      sigemptyset (&new_mask);
+      sigaddset (&new_mask, SIGIO);
+      pthread_sigmask (SIG_BLOCK, &new_mask, 0);
+      pthread_kill (main_thread, SIGIO);
+      return;
+    }
+#endif /* HAVE_GTK_AND_PTHREAD */
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
      must reestablish each time */
--- a/src/lisp.h	Tue Dec 07 08:09:10 2004 +0000
+++ b/src/lisp.h	Tue Dec 07 08:25:43 2004 +0000
@@ -2457,6 +2457,7 @@
 /* Defined in alloc.c */
 extern void check_pure_size P_ ((void));
 extern void allocate_string_data P_ ((struct Lisp_String *, int, int));
+extern void reset_malloc_hooks P_ ((void));
 extern void uninterrupt_malloc P_ ((void));
 extern void malloc_warning P_ ((char *));
 extern void memory_full P_ ((void));