unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Mac OS X - Hang / C-g problem patch
@ 2002-12-04 18:06 Steven Tamm
  2002-12-05  6:48 ` Andrew Choi
  0 siblings, 1 reply; 11+ messages in thread
From: Steven Tamm @ 2002-12-04 18:06 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2350 bytes --]

I just found some free time on my hands and got back around to working 
on the problem where in the carbon gui, C-g does not interrupt 
synchronous subprocesses.  This caused much consternation and after 
checking with some people at apple, there was no easy way.  The 
alternatives were to finish my Jaguar/MT UI patch (which I won't go 
into), or to make all blocking reads be in a separate thread.

This patch overrides read to call sys_read.  sys_read will call 
darwin's read if inhibit_window_system, noninteractive, if the file 
descriptor is not FIFO, or if the file descriptor is non-blocking.  So 
it only differs when blocks with pipes and sockets.  It works by 
spawning a worker thread that handles the read while waiting on a 
MPQueue (chose this instead of pthread_cond for simplicity).  When a 
potentially hanging read is started, it posts a message to the worker 
threads queue and then blocks for an event coming back from the worker 
thread and also KeyUp events.  If the worker thread event comes back to 
the main thread, it returns like normal.  If a keyup event comes in, it 
is tested to see if it is the quit_char, and if so, the worker thread 
is signalled and Fsignal is called to unroll the call.  It seems to 
work and hopefully it plugs a large hole.

Issues:
1.  Uses fstat and fcntl way too often.  These calls aren't 
extraordinarily expensive and I didn't notice a difference, but your 
mileage may vary.
2.  Traps keyUp instead of keyDown.  This behavior is broken because it 
makes emacs think C-g has been called twice.  But it makes things much 
simpler.  Otherwise, the main thread would have to dispatch all events 
to the kbd_buffer, which with the current event handling is an issue.  
If we switched to Carbon Event Handers, this would be a non-issue (in 
fact there would be less code).
3.  Only works when quit_char is C-g.  There is docs on how to fix it, 
but I didn't want to wait.
4.  Only works on darwin (due to use of pthread_kill).  I probably 
should have put in an ifdef...

Not tested:
1.  Sending random signals to the emacs process to see if the reads 
continue.  There may need to be some checking in signal handlers 
elsewhere to cause the secondary thread to break.
2.  Memory leaks.

I would appreciate any/all Mac OS X developers to try the patch and let 
me know how it goes.

-Steven

[-- Attachment #2: carbon_quit_char.patch --]
[-- Type: application/octet-stream, Size: 8777 bytes --]

Index: src/sysdep.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/sysdep.c,v
retrieving revision 1.245
diff -u -d -b -w -r1.245 sysdep.c
--- src/sysdep.c	22 Nov 2002 12:22:43 -0000	1.245
+++ src/sysdep.c	4 Dec 2002 17:52:59 -0000
@@ -69,6 +69,10 @@
 #endif
 #endif /* not WINDOWSNT */
 
+#ifdef HAVE_CARBON
+#define read sys_read
+#endif
+
 /* Does anyone other than VMS need this? */
 #ifndef fwrite
 #define sys_fwrite fwrite
Index: src/macterm.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/macterm.c,v
retrieving revision 1.26
diff -u -d -b -w -r1.26 macterm.c
--- src/macterm.c	2 Dec 2002 17:13:45 -0000	1.26
+++ src/macterm.c	4 Dec 2002 17:53:02 -0000
@@ -12630,7 +12630,7 @@
 				expected
 				? TicksToEventTime (app_sleep_time)
 				: 0,
-				true, &eventRef);
+				kEventRemoveFromQueue, &eventRef);
   if (!rneResult)
     {
       /* Handle new events */
@@ -13446,6 +13446,60 @@
 \f
 #ifdef MAC_OSX
 void
+mac_check_bundle()
+{
+  extern int inhibit_window_system;
+  extern int noninteractive;
+  CFBundleRef appsBundle;
+  pid_t child;
+
+  /* No need to test if already -nw*/
+  if (inhibit_window_system || noninteractive)
+    return;
+
+  appsBundle = CFBundleGetMainBundle();
+  if (appsBundle != NULL)
+    {
+      CFStringRef cfBI = CFSTR("CFBundleIdentifier");
+      CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
+      /* We found the bundle identifier, now we know we are valid. */
+      if (res != NULL)
+	{
+	  CFRelease(res);
+	  return;
+	}
+    }
+
+  /* Now we must find the "bundled" executable and exec it */
+  child = fork();
+  if (child < 0) 
+    {
+      /* If there is an error, try to keep going inside the terminal */
+      inhibit_window_system = 1;
+    }
+  if (!child) 
+    {
+      int i;
+      extern char **initial_argv;
+      extern int initial_argc;
+      char *newApp = "/Applications/Emacs.app/Contents/MacOS/Emacs";
+      register const unsigned char **new_argv =
+	(const unsigned char **) alloca ((initial_argc+1) * sizeof(char*));
+      new_argv[0] = newApp;
+      for (i = 1; i < initial_argc; i++) 
+	new_argv[i] = initial_argv[i];
+      new_argv[initial_argc]=NULL;  /* Will point to last entry*/
+      execv(newApp, new_argv);
+      _exit(-1);
+    } 
+  else
+    {
+      /* Started successfully */
+      exit(0);
+    }
+}
+
+void
 MakeMeTheFrontProcess ()
 {
   ProcessSerialNumber psn;
@@ -13454,6 +13508,195 @@
   err = GetCurrentProcess (&psn);
   if (err == noErr)
     (void) SetFrontProcess (&psn);
+}
+
+/* Fix C-g hang in emacs by placing blocking IO in separate thread.  */
+#define kEventClassEmacs 'EMAx'
+#define kEventEmacsReadDone 'read'
+#define kEventParamErrorNo 'errn'
+MPQueueID reader_queue = NULL;
+pthread_t mac_reader_thread = NULL;
+
+void 
+mac_reader_loop (void *arg)
+{
+  sigset_t sigs;
+  sigfillset(&sigs);
+  sigdelset(&sigs, SIGINT);
+  sigdelset(&sigs, SIGURG);
+  pthread_sigmask(SIG_SETMASK, &sigs, NULL);
+  while (1) 
+    {
+      int fildes;
+      char *buf;
+      unsigned int nbyte;
+      ssize_t result;
+      int curerr = 0;
+      EventRef event;
+
+      MPWaitOnQueue(reader_queue, (void**)&fildes, (void**)&buf, (void**)&nbyte, kDurationForever);
+      result = read(fildes, buf, nbyte);   
+      if (result < 0)
+	curerr = errno;
+
+      CreateEvent(NULL, kEventClassEmacs, kEventEmacsReadDone,
+		  0, kEventAttributeUserEvent, &event);
+      SetEventParameter(event, kEventParamDirectObject, typeUInt32, 
+			sizeof(UInt32), &result);
+      SetEventParameter(event, kEventParamErrorNo, typeUInt32, 
+			sizeof(UInt32), &curerr);
+      PostEventToQueue(GetMainEventQueue(), event,
+		       kEventPriorityHigh);
+      ReleaseEvent(event);
+
+      /* Post any stolen events back to the event queue at once */
+    }
+}
+
+UInt32 mac_quit_char_keycode;
+UInt32 mac_quit_char_modifiers;
+#define kModifierMask (controlKey|cmdKey|optionKey|shiftKey)
+
+static OSStatus
+mac_register_quit_char()
+{
+  UInt32 modifiers = ctrl_modifier;
+  mac_quit_char_modifiers = 0;
+  mac_quit_char_keycode = 0x05;  
+  /* FIXME: if quit_char is not C-g, then we need to map from 
+     ascii to keyCode.  Look at <architecture/adb_kb_map.h> for details */
+  /*http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
+  
+  /* Map modifiers */
+  if (modifiers & ctrl_modifier)  mac_quit_char_modifiers |= macCtrlKey;
+  if (modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
+  if (modifiers & meta_modifier)  mac_quit_char_modifiers |= macMetaKey;
+  if (modifiers & alt_modifier)   mac_quit_char_modifiers |= macAltKey;
+}
+
+static void
+initialize_reader_thread()
+{
+  if (!mac_reader_thread)
+    {
+      int result;
+      mac_register_quit_char();
+      MPCreateQueue(&reader_queue);
+      if (!pthread_create(&mac_reader_thread, NULL, mac_reader_loop, NULL))
+	{
+	  /* For some reason pthread_create is working, but returning 200. */
+	}
+    }
+}
+
+static UInt32
+mac_blocked_io_call()
+{
+  UInt32 result;
+  EventRef event;
+  OSStatus err;
+
+  static EventTypeSpec mac_reader_events[] = {
+    {kEventClassKeyboard, kEventRawKeyUp}, /* See note below*/
+    {kEventClassEmacs, kEventEmacsReadDone}
+  };
+
+  /* This relies on the fact that keyUp events are ignored by emacs,
+   and are, in general, ignored by everything else.  This means we
+   can suck all the events off the queue and remain in a wait state.
+   Using keydown causes issues because you cannot leave the event on 
+   the queue, or this call will be constantly called with that event.
+   So to use keydown, you must either save the event for posting later
+   or generate the input_event here.  Generating the input_event is
+   probably better.
+
+   The switch to keyDown should be made to make the behavior uniform
+   across platforms, but this would require splitting up XTread_socket.
+   Hopefully, then the event handling will be split into a separate file.
+   Using standard carbon event handlers with the kbd_buffer_store_event
+   code would probably be best.
+  */
+  while (1) 
+    {
+      err = ReceiveNextEvent(2, mac_reader_events, kEventDurationForever,
+			     kEventRemoveFromQueue, &event);
+      if (err != noErr) 
+	fprintf(stderr, "Got Error in RNE: %d", err);
+      UInt32 eClass = GetEventClass(event);
+      if (eClass == kEventClassEmacs) 
+	{
+	  int threadErrno = 0;
+	  err = GetEventParameter (event, kEventParamDirectObject, typeUInt32,
+				   NULL, sizeof(UInt32), NULL, &result);
+	  if (err != noErr) 
+	    fprintf(stderr, "Got Error in RNE: %d", err);
+	  /* Need to get errno from read thread to main thread here. */
+	  err = GetEventParameter (event, kEventParamErrorNo, typeUInt32,
+				   NULL, sizeof(UInt32), NULL, &threadErrno);
+	  if (err != noErr) 
+	    fprintf(stderr, "Got Error in RNE: %d", err);
+	  errno = threadErrno;
+	  break;
+	}
+      else 
+	{
+	  UInt32 keyCode, modifiers;
+	  GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL,
+			    sizeof(UInt32), NULL, &keyCode);
+	  if (keyCode == mac_quit_char_keycode)
+	    {
+	      GetEventParameter(event, kEventParamKeyModifiers, typeUInt32,
+				NULL, sizeof(UInt32), NULL, &modifiers);
+	      if ((modifiers & kModifierMask) == mac_quit_char_modifiers) 
+		{
+		  /* Signal the read to stop */
+		  pthread_kill(mac_reader_thread, SIGURG); 
+
+		  /* Instead of signalling directly, possibly use 
+		     kbd_buffer_store_event with a quit_char event.  */
+		  Fsignal (Qquit, Qnil);		  
+		  /* NOTREACHED */
+		  result = -1;
+		}
+	    }
+	}
+    }
+  ReleaseEvent(event);
+  return result;
+}
+
+int
+sys_read (fildes, buf, nbyte)
+     int fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+#if !USE_CARBON_EVENTS
+  return read(fildes, buf, nbyte);
+#endif
+
+  /* If not GUI, use default behavior */
+
+  if (inhibit_window_system || noninteractive)
+    return read(fildes, buf, nbyte);
+
+  /* Only use on sync threaded read on blocking pipes and sockets */
+  {
+    struct stat stat;
+    fstat(fildes, &stat);
+    if (!S_ISFIFO(stat.st_mode) || fcntl(fildes, F_GETFL, 0) & O_NONBLOCK)
+      return read(fildes, buf, nbyte);
+  }
+
+  initialize_reader_thread();
+
+  MPNotifyQueue(reader_queue, (void*)fildes, buf, (void*)nbyte);
+
+  {
+    int result;
+    result = mac_blocked_io_call();
+    return result;
+  }
 }
 #endif /* MAC_OSX */
 

[-- Attachment #3: Type: text/plain, Size: 137 bytes --]


P.S.  This patch also contains the mac_check_bundle code I was playing 
around with to get emacs from the command line to start the GUI.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-04 18:06 Mac OS X - Hang / C-g problem patch Steven Tamm
@ 2002-12-05  6:48 ` Andrew Choi
  2002-12-05 16:32   ` Steven Tamm
  2002-12-08  6:15   ` Steven Tamm
  0 siblings, 2 replies; 11+ messages in thread
From: Andrew Choi @ 2002-12-05  6:48 UTC (permalink / raw)
  Cc: emacs-devel

Steven Tamm <steventamm@mac.com> writes:

> I just found some free time on my hands and got back around to working
> on the problem where in the carbon gui, C-g does not interrupt
> synchronous subprocesses.  This caused much consternation and after
> checking with some people at apple, there was no easy way.  The
> alternatives were to finish my Jaguar/MT UI patch (which I won't go
> into), or to make all blocking reads be in a separate thread.  [...]

Hi Steven,

I've checked that your patch works as advertised.

I've worked out a simpler solution that uses polling though.  The idea
is to patch `read' to call `select' to check for available input.  If
none is after one second, poll for a user-cancel and check for input
again and repeat.  Since I've used CheckEventQueueForUserCancel, the
command-period key is used instead of C-g.  We can probably change it to
C-g if we want.

The patch also handles the following cases: when Emacs is stuck in a
loop executing Lisp code and when it is stuck waiting for select instead
of read (e.g., sleep-for).

Performance will not be a problem except perhaps for the check in
`eval'.

Andrew.

Index: eval.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/eval.c,v
retrieving revision 1.197
diff -u -r1.197 eval.c
--- eval.c	21 Nov 2002 17:33:01 -0000	1.197
+++ eval.c	5 Dec 2002 05:22:48 -0000
@@ -27,6 +27,9 @@
 #include "keyboard.h"
 #include "dispextern.h"
 #include <setjmp.h>
+#ifdef MAC_OSX
+#include <signal.h>
+#endif
 
 /* This definition is duplicated in alloc.c and keyboard.c */
 /* Putting it in lisp.h makes cc bomb out! */
@@ -2154,6 +2157,12 @@
   if (backtrace.debug_on_exit)
     val = call_debugger (Fcons (Qexit, Fcons (val, Qnil)));
   backtrace_list = backtrace.next;
+
+#ifdef MAC_OSX
+  if (CheckEventQueueForUserCancel ())
+    kill (getpid (), SIGINT);
+#endif
+
   return val;
 }
 \f
Index: keyboard.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v
retrieving revision 1.716
diff -u -r1.716 keyboard.c
--- keyboard.c	22 Nov 2002 12:23:13 -0000	1.716
+++ keyboard.c	5 Dec 2002 05:23:00 -0000
@@ -10494,6 +10494,11 @@
   poll_suppress_count = 1;
   start_polling ();
 #endif
+
+#ifdef MAC_OSX
+  /* At least provide an escape route since C-g doesn't work.  */
+  signal (SIGINT, interrupt_signal);
+#endif
 }
 
 /* This type's only use is in syms_of_keyboard, to initialize the
Index: mac.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/mac.c,v
retrieving revision 1.10
diff -u -r1.10 mac.c
--- mac.c	18 Oct 2002 10:00:10 -0000	1.10
+++ mac.c	5 Dec 2002 05:23:01 -0000
@@ -2748,6 +2748,8 @@
 }
 
 #ifdef MAC_OSX
+#include <signal.h>
+
 #undef select
 
 extern int inhibit_window_system;
@@ -2768,9 +2770,60 @@
   if (!inhibit_window_system && rfds && FD_ISSET (0, rfds))
     return 1;
   else
-    return select (n, rfds, wfds, efds, timeout);
+    {
+      EMACS_TIME end_time, now;
+
+      EMACS_GET_TIME (end_time);
+      EMACS_ADD_TIME (end_time, end_time, *timeout);
+
+      do
+	{
+	  int r;
+	  EMACS_TIME one_second;
+
+	  EMACS_SET_SECS (one_second, 1);
+	  EMACS_SET_USECS (one_second, 0);
+	  
+	  if ((r = select (n, rfds, wfds, efds, &one_second)) > 0)
+	    return r;
+	  
+	  if (CheckEventQueueForUserCancel ())
+	    {
+	      kill (getpid (), SIGINT);
+	      return 0;
+	    }
+
+	  EMACS_GET_TIME (now);
+	  EMACS_SUB_TIME (now, end_time, now);
+	}
+      while (!EMACS_TIME_NEG_P (now));
+
+      return 0;
+    }
 }
 
+#undef read
+int sys_read (fds, buf, nbyte)
+     int fds;
+     char *buf;
+     unsigned int nbyte;
+{
+  SELECT_TYPE rfds;
+  EMACS_TIME one_second;
+  int r;
+  
+  do 
+    {
+      FD_ZERO (&rfds);
+      FD_SET (fds, &rfds);
+
+      EMACS_SET_SECS (one_second, 1);
+      EMACS_SET_USECS (one_second, 0);
+    }  
+  while (sys_select (fds+1, &rfds, 0, 0, &one_second) == 0);
+
+  return read (fds, buf, nbyte);
+}
 
 /* Set up environment variables so that Emacs can correctly find its
    support files when packaged as an application bundle.  Directories
Index: sysdep.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/sysdep.c,v
retrieving revision 1.245
diff -u -r1.245 sysdep.c
--- sysdep.c	22 Nov 2002 12:22:43 -0000	1.245
+++ sysdep.c	5 Dec 2002 05:23:04 -0000
@@ -69,6 +69,10 @@
 #endif
 #endif /* not WINDOWSNT */
 
+#ifdef HAVE_CARBON
+#define read sys_read
+#endif
+
 /* Does anyone other than VMS need this? */
 #ifndef fwrite
 #define sys_fwrite fwrite

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-05  6:48 ` Andrew Choi
@ 2002-12-05 16:32   ` Steven Tamm
  2002-12-05 23:47     ` Andrew Choi
  2002-12-08  6:15   ` Steven Tamm
  1 sibling, 1 reply; 11+ messages in thread
From: Steven Tamm @ 2002-12-05 16:32 UTC (permalink / raw)
  Cc: emacs-devel

I thought about doing it this way, because I wanted to avoid polling.  
And the call to CheckEventQueueForUserCancel I didn't even bother 
trying because to get C-g to work in the same manner would be quite 
expensive.  (To do it you would have to put in a call to RNE() for a 
non-existent event type before calling FindSpecificEventsInQueue).

There is also a third way.  Use osx's global hotkeys.  The good/bad 
thing about global hotkeys is that the events are sent to every 
application that cares regardless of whether they were the frontmost 
application.  Fork off a process that registers C-g as a global hotkey. 
  Whenever that process gets the hotkey and its parent app is the 
frontmost process, send a kill(SIGINT).  I sent this to the carbon list 
yesterday and am waiting for the guy from apple to respond.  If this 
works with little hassle, I would prefer this solution.  This would 
work in all circumstances and would not require putting in patches 
everywhere to check if C-g is on the system queue.

What do you think?

-Steven

On Wednesday, December 4, 2002, at 10:48  PM, Andrew Choi wrote:

> Steven Tamm <steventamm@mac.com> writes:
>
>> I just found some free time on my hands and got back around to working
>> on the problem where in the carbon gui, C-g does not interrupt
>> synchronous subprocesses.  This caused much consternation and after
>> checking with some people at apple, there was no easy way.  The
>> alternatives were to finish my Jaguar/MT UI patch (which I won't go
>> into), or to make all blocking reads be in a separate thread.  [...]
>
> Hi Steven,
>
> I've checked that your patch works as advertised.
>
> I've worked out a simpler solution that uses polling though.  The idea
> is to patch `read' to call `select' to check for available input.  If
> none is after one second, poll for a user-cancel and check for input
> again and repeat.  Since I've used CheckEventQueueForUserCancel, the
> command-period key is used instead of C-g.  We can probably change it 
> to
> C-g if we want.
>
> The patch also handles the following cases: when Emacs is stuck in a
> loop executing Lisp code and when it is stuck waiting for select 
> instead
> of read (e.g., sleep-for).
>
> Performance will not be a problem except perhaps for the check in
> `eval'.
>
> Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-05 16:32   ` Steven Tamm
@ 2002-12-05 23:47     ` Andrew Choi
  2002-12-06 18:15       ` Steven Tamm
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Choi @ 2002-12-05 23:47 UTC (permalink / raw)
  Cc: emacs-devel

Steven Tamm <steventamm@mac.com> writes:

> I thought about doing it this way, because I wanted to avoid polling.
> And the call to CheckEventQueueForUserCancel I didn't even bother
> trying because to get C-g to work in the same manner would be quite
> expensive.  (To do it you would have to put in a call to RNE() for a
> non-existent event type before calling FindSpecificEventsInQueue).

Hi Steven,

I'm not sure it will be much worse than CheckEventQueueForUserCancel
unless we code it up and run a profiler on it.  Most likely, the event
queue will just be empty most of the time we check it.

Polling the event queue every time through eval will no doubt cost an
overhead.  Polling is not a bad solution to detect the cancel key in
`select' and `read' though.

> There is also a third way.  Use osx's global hotkeys.  The good/bad
> thing about global hotkeys is that the events are sent to every
> application that cares regardless of whether they were the frontmost
> application.  Fork off a process that registers C-g as a global
> hotkey. Whenever that process gets the hotkey and its parent app is
> the frontmost process, send a kill(SIGINT).  I sent this to the carbon
> list yesterday and am waiting for the guy from apple to respond.  If
> this works with little hassle, I would prefer this solution.  This
> would work in all circumstances and would not require putting in
> patches everywhere to check if C-g is on the system queue.
> 
> What do you think?

That doesn't seem like a good solution: an event that every application
sees?  But please do let me know what additional information you can get
from the carbon mailing list.  In terms of program architecture and
efficiency, your very first attempt was the best: using a separate
thread to capture all input and pass that on to a main thread.  But hey
I'm not working on it, so I really shouldn't be saying anything :-).

Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-05 23:47     ` Andrew Choi
@ 2002-12-06 18:15       ` Steven Tamm
  0 siblings, 0 replies; 11+ messages in thread
From: Steven Tamm @ 2002-12-06 18:15 UTC (permalink / raw)
  Cc: emacs-devel

>> <polling for events in eval>
>
> I'm not sure it will be much worse than CheckEventQueueForUserCancel
> unless we code it up and run a profiler on it.  Most likely, the event
> queue will just be empty most of the time we check it.
>
> Polling the event queue every time through eval will no doubt cost an
> overhead.  Polling is not a bad solution to detect the cancel key in
> `select' and `read' though.

Polling is not bad in the select/read case, and it probably should be 
checked in (once I get the answer from the carbon-development list 
about FindSpecificEventInQueue).  As for the test in eval, I'll run the 
profiler on it this weekend and see how much it adds to the overall 
cost of eval.

For the list, What would be a good simple-to-execute lisp function to 
profile to measure changes to Feval?  I was going to use regexp-opt.

>> <stuff about hotkeys>
>
> That doesn't seem like a good solution: an event that every application
> sees?  But please do let me know what additional information you can 
> get
> from the carbon mailing list.  In terms of program architecture and
> efficiency, your very first attempt was the best: using a separate
> thread to capture all input and pass that on to a main thread.  But hey
> I'm not working on it, so I really shouldn't be saying anything :-).

It works a little differently than this.  The global hotkey is only 
sent to the application that requests it.  The problem is that while 
the hotkey is registered, it is NEVER sent to any other application.  
So it won't work (because not passing C-g to the terminal application 
is unacceptable).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-05  6:48 ` Andrew Choi
  2002-12-05 16:32   ` Steven Tamm
@ 2002-12-08  6:15   ` Steven Tamm
  2002-12-08 20:51     ` Andrew Choi
  2002-12-09 10:13     ` dme
  1 sibling, 2 replies; 11+ messages in thread
From: Steven Tamm @ 2002-12-08  6:15 UTC (permalink / raw)
  Cc: emacs-devel

Hi Andrew (and others interested in this problem),

I've checked in your patch with a few modification.
First, I added code to check for C-g instead of C-. to macterm.c.  
Right now it will only work if the quit_char is C-g, but I plan on 
adding code that will convert from ascii -> keycode later.  Anywhere 
this check should be done, call mac_check_for_quit_char().
Second, I made sys_read depend on sys_select to do the blocking.  I 
also made sys_select handle NULL as the timeout (so that sys_read could 
block forever)
Third, I didn't use signals, but instead sent the quit_char as an 
input_event to kbd_buffer_store_event.  This seemed like a better idea 
than directly using signals because things like last_event_timestamp 
are updated.
I left the call to mac_check_for_quit_char in Feval with a note in the 
cvs log that it might be removed.

I tried to run some profiling tests but none of the data I got seemed 
useful.  It seems to not be that expensive a call.  In any case I filed 
a couple radar bugs to see if the WindowManager could be programmed to 
send a signal based on a hotkey.  It's bug 3121160  (Allow ability to 
have a keypress cause a signal in Carbon).  I also reported a bug to be 
able to set the main event queue for an application to be a secondary 
thread, but doubt that it will go anywhere due to thread safety issues.

-Steven

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-08  6:15   ` Steven Tamm
@ 2002-12-08 20:51     ` Andrew Choi
  2002-12-09 10:13     ` dme
  1 sibling, 0 replies; 11+ messages in thread
From: Andrew Choi @ 2002-12-08 20:51 UTC (permalink / raw)
  Cc: emacs-devel

Steven Tamm <steventamm@mac.com> writes:

> I've checked in your patch with a few modification.  First, I added
> code to check for C-g instead of C-. to macterm.c.  [...]

Hi Steven,

Thank you for working on this.  I can't look closely at your changes
right now because my Emacs is experiencing mysterious crashes.  These
started in the CVS code a few days ago and seem to happen during garbage
collection while I'm using Gnus.  I don't know if it is due to a problem
with my own installation, a Mac-specific problem, or a more general
problem.  Anyway I'll try to track it down.  Thanks again for your
modifications.  It will be nice to have the use of C-g!

Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-08  6:15   ` Steven Tamm
  2002-12-08 20:51     ` Andrew Choi
@ 2002-12-09 10:13     ` dme
  2002-12-09 16:42       ` Andrew Choi
  2002-12-09 18:09       ` Steven Tamm
  1 sibling, 2 replies; 11+ messages in thread
From: dme @ 2002-12-09 10:13 UTC (permalink / raw)


* steventamm@mac.com [2002-12-08 06:15:21]
> [...]

I updated and re-configured, rebuilt, etc.

When attempting to use ERC, emacs reliably hangs in sys_select(), due
to there being no bits set in rfds.  Faking some bits using gdb lets
emacs carry on a little, but it hangs again quite quickly.  The trace
is:

(gdb) where
#0  0x90025cc8 in select ()
#1  0x00117cb0 in sys_select (n=10, rfds=0xbfffdf60, wfds=0x0, efds=0x0, timeout=0x0) at mac.c:2789
#2  0x00117dd8 in sys_read (fds=-1073750176, buf=0x1 <Address 0x1 out of bounds>, nbyte=3221217008) at mac.c:2818
#3  0x0007b520 in emacs_read (fildes=9, buf=0xbfffe0b0 "", nbyte=1024) at sysdep.c:3279
#4  0x00102b80 in read_process_output (proc=1108160672, channel=9) at process.c:4390
#5  0x00102694 in wait_reading_process_input (time_limit=30, microsecs=0, read_kbd=2571592, do_display=1) at process.c:4134
#6  0x0000c454 in sit_for (sec=30, usec=0, reading=1, display=1, initial_display=0) at dispnew.c:6247
#7  0x0006674c in read_char (commandflag=1, nmaps=4, maps=0xbfffefa0, prev_event=274970324, used_mouse_menu=0xbffff0a4) at keyboard.c:2630
#8  0x0006e754 in read_key_sequence (keybuf=0xbffff170, bufsize=33599088, prompt=274970324, dont_downcase_last=2362820, can_return_switch_frame=1, fix_current_buffer=2350356) at keyboard.c:8505
#9  0x0006415c in command_loop_1 () at keyboard.c:1473
#10 0x000c943c in internal_condition_case (bfun=0x63d34 <command_loop_1>, handlers=275016892, hfun=0x636e4 <cmd_error>) at eval.c:1352
#11 0x00063b14 in command_loop_2 () at keyboard.c:1274
#12 0x000c8edc in internal_catch (tag=4, func=0x63ad4 <command_loop_2>, arg=274970324) at eval.c:1112
#13 0x00063a6c in command_loop () at keyboard.c:1253
#14 0x00063480 in recursive_edit_1 () at keyboard.c:969
#15 0x00063608 in Frecursive_edit () at keyboard.c:1025
#16 0x000620dc in main (argc=0, argv=0xbffffdf8) at emacs.c:1647
#17 0x00003c48 in _start (argc=50, argv=0x0, envp=0x23b2b4) at /SourceCache/Csu/Csu-45/crt.c:267
#18 0x00003ac8 in start ()
(gdb) up
#1  0x00117cb0 in sys_select (n=10, rfds=0xbfffdf60, wfds=0x0, efds=0x0, timeout=0x0) at mac.c:2789
2789              if ((r = select (n, rfds, wfds, efds, &one_second)) > 0)
(gdb) print *rfds
$27 = {
  fds_bits = {0 <repeats 32 times>}
}
(gdb) 

Has anyone else seen this ?  I'll carry on looking...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-09 10:13     ` dme
@ 2002-12-09 16:42       ` Andrew Choi
  2002-12-09 18:09       ` Steven Tamm
  1 sibling, 0 replies; 11+ messages in thread
From: Andrew Choi @ 2002-12-09 16:42 UTC (permalink / raw)


dme@dme.org writes:

> I updated and re-configured, rebuilt, etc.
> 
> When attempting to use ERC, emacs reliably hangs in sys_select(), due
> to there being no bits set in rfds.  Faking some bits using gdb lets
> emacs carry on a little, but it hangs again quite quickly.  [...]
> 
> Has anyone else seen this ?  I'll carry on looking...

I'm having a similar problem in Gnus too.  I'll try to look at the patch
when I clear up some other problems.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-09 10:13     ` dme
  2002-12-09 16:42       ` Andrew Choi
@ 2002-12-09 18:09       ` Steven Tamm
  2002-12-10 12:38         ` dme
  1 sibling, 1 reply; 11+ messages in thread
From: Steven Tamm @ 2002-12-09 18:09 UTC (permalink / raw)
  Cc: emacs-devel

Just remembered something from my async-read patch; read shouldn't call 
select if the fd is non-blocking (which may or may not be the issue 
here)
Could you try this patch?


Index: src/mac.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/mac.c,v
retrieving revision 1.11
diff -u -d -b -w -r1.11 mac.c
--- src/mac.c   8 Dec 2002 05:58:34 -0000       1.11
+++ src/mac.c   9 Dec 2002 17:50:45 -0000
@@ -32,6 +32,7 @@
  #include <pwd.h>
  #include <sys/param.h>
  #include <stdlib.h>
+#include <fcntl.h>
  #if __MWERKS__
  #include <unistd.h>
  #endif
@@ -2811,7 +2812,8 @@
    int r;

    /* Use select to block on IO while still checking for quit_char */
-  if (!inhibit_window_system && !noninteractive)
+  if (!inhibit_window_system && !noninteractive &&
+      ! (fcntl(fds, F_GETFL, 0) & O_NONBLOCK))
      {
        FD_ZERO (&rfds);
        FD_SET (fds, &rfds);

==
One other thing: does pressing C-g cause it to quit, or does it just 
hang?

-Steven

On Monday, December 9, 2002, at 02:13  AM, dme@dme.org wrote:

> * steventamm@mac.com [2002-12-08 06:15:21]
>> [...]
>
> I updated and re-configured, rebuilt, etc.
>
> When attempting to use ERC, emacs reliably hangs in sys_select(), due
> to there being no bits set in rfds.  Faking some bits using gdb lets
> emacs carry on a little, but it hangs again quite quickly.  The trace
> is:
>
> (gdb) where
> #0  0x90025cc8 in select ()
> #1  0x00117cb0 in sys_select (n=10, rfds=0xbfffdf60, wfds=0x0, 
> efds=0x0, timeout=0x0) at mac.c:2789
> #2  0x00117dd8 in sys_read (fds=-1073750176, buf=0x1 <Address 0x1 out 
> of bounds>, nbyte=3221217008) at mac.c:2818
> #3  0x0007b520 in emacs_read (fildes=9, buf=0xbfffe0b0 "", nbyte=1024) 
> at sysdep.c:3279
> #4  0x00102b80 in read_process_output (proc=1108160672, channel=9) at 
> process.c:4390
> #5  0x00102694 in wait_reading_process_input (time_limit=30, 
> microsecs=0, read_kbd=2571592, do_display=1) at process.c:4134
> #6  0x0000c454 in sit_for (sec=30, usec=0, reading=1, display=1, 
> initial_display=0) at dispnew.c:6247
> #7  0x0006674c in read_char (commandflag=1, nmaps=4, maps=0xbfffefa0, 
> prev_event=274970324, used_mouse_menu=0xbffff0a4) at keyboard.c:2630
> #8  0x0006e754 in read_key_sequence (keybuf=0xbffff170, 
> bufsize=33599088, prompt=274970324, dont_downcase_last=2362820, 
> can_return_switch_frame=1, fix_current_buffer=2350356) at 
> keyboard.c:8505
> #9  0x0006415c in command_loop_1 () at keyboard.c:1473
> #10 0x000c943c in internal_condition_case (bfun=0x63d34 
> <command_loop_1>, handlers=275016892, hfun=0x636e4 <cmd_error>) at 
> eval.c:1352
> #11 0x00063b14 in command_loop_2 () at keyboard.c:1274
> #12 0x000c8edc in internal_catch (tag=4, func=0x63ad4 
> <command_loop_2>, arg=274970324) at eval.c:1112
> #13 0x00063a6c in command_loop () at keyboard.c:1253
> #14 0x00063480 in recursive_edit_1 () at keyboard.c:969
> #15 0x00063608 in Frecursive_edit () at keyboard.c:1025
> #16 0x000620dc in main (argc=0, argv=0xbffffdf8) at emacs.c:1647
> #17 0x00003c48 in _start (argc=50, argv=0x0, envp=0x23b2b4) at 
> /SourceCache/Csu/Csu-45/crt.c:267
> #18 0x00003ac8 in start ()
> (gdb) up
> #1  0x00117cb0 in sys_select (n=10, rfds=0xbfffdf60, wfds=0x0, 
> efds=0x0, timeout=0x0) at mac.c:2789
> 2789              if ((r = select (n, rfds, wfds, efds, &one_second)) 
> > 0)
> (gdb) print *rfds
> $27 = {
>   fds_bits = {0 <repeats 32 times>}
> }
> (gdb)
>
> Has anyone else seen this ?  I'll carry on looking...
>
>
>
>
> _______________________________________________
> Emacs-devel mailing list
> Emacs-devel@gnu.org
> http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Mac OS X - Hang / C-g problem patch
  2002-12-09 18:09       ` Steven Tamm
@ 2002-12-10 12:38         ` dme
  0 siblings, 0 replies; 11+ messages in thread
From: dme @ 2002-12-10 12:38 UTC (permalink / raw)


* steventamm@mac.com [2002-12-09 18:09:37]
> Just remembered something from my async-read patch; read shouldn't
> call select if the fd is non-blocking (which may or may not be the
> issue here)
> Could you try this patch?

This improves things a lot.  Brief testing indicates that erc now
works.  I'll test some more and report if I discover any other
problems.

Thanks very much.

> One other thing: does pressing C-g cause it to quit, or does it just
> hang?

In the previous situation, pressing C-g did nothing after emacs was
already hung.  Slight testing before it hung indicated that C-g
behaved as expected.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2002-12-10 12:38 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-04 18:06 Mac OS X - Hang / C-g problem patch Steven Tamm
2002-12-05  6:48 ` Andrew Choi
2002-12-05 16:32   ` Steven Tamm
2002-12-05 23:47     ` Andrew Choi
2002-12-06 18:15       ` Steven Tamm
2002-12-08  6:15   ` Steven Tamm
2002-12-08 20:51     ` Andrew Choi
2002-12-09 10:13     ` dme
2002-12-09 16:42       ` Andrew Choi
2002-12-09 18:09       ` Steven Tamm
2002-12-10 12:38         ` dme

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).