From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Steven Tamm Newsgroups: gmane.emacs.devel Subject: Mac OS X - Hang / C-g problem patch Date: Wed, 4 Dec 2002 10:06:10 -0800 Sender: emacs-devel-admin@gnu.org Message-ID: <11A91199-07B3-11D7-AADA-00039390AB82@mac.com> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 (Apple Message framework v548) Content-Type: multipart/mixed; boundary=Apple-Mail-7-588428640 X-Trace: main.gmane.org 1039025242 15135 80.91.224.249 (4 Dec 2002 18:07:22 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Wed, 4 Dec 2002 18:07:22 +0000 (UTC) Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18Jdvc-0003vl-00 for ; Wed, 04 Dec 2002 19:07:20 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 18Je5i-0000bN-00 for ; Wed, 04 Dec 2002 19:17:46 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18JdxM-0000gE-00; Wed, 04 Dec 2002 13:09:08 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10.13) id 18Jdwx-0000PB-00 for emacs-devel@gnu.org; Wed, 04 Dec 2002 13:08:43 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10.13) id 18Jdwu-0000OT-00 for emacs-devel@gnu.org; Wed, 04 Dec 2002 13:08:42 -0500 Original-Received: from smtpout.mac.com ([17.250.248.87]) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18Jdun-0007tb-00 for emacs-devel@gnu.org; Wed, 04 Dec 2002 13:06:29 -0500 Original-Received: from asmtp01.mac.com (asmtp01-qfe3 [10.13.10.65]) by smtpout.mac.com (Xserve/MantshX 2.0) with ESMTP id gB4I6C8W022830 for ; Wed, 4 Dec 2002 10:06:22 -0800 (PST) Original-Received: from mac.com ([12.236.43.16]) by asmtp01.mac.com (Netscape Messaging Server 4.15) with ESMTP id H6LWYB00.GYD for ; Wed, 4 Dec 2002 10:06:11 -0800 Original-To: emacs-devel@gnu.org X-Mailer: Apple Mail (2.548) Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:9861 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:9861 --Apple-Mail-7-588428640 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed 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 --Apple-Mail-7-588428640 Content-Disposition: attachment; filename=carbon_quit_char.patch Content-Transfer-Encoding: quoted-printable Content-Type: application/octet-stream; x-unix-mode=0644; name="carbon_quit_char.patch" Index:=20src/sysdep.c=0A= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0ARCS=20file:=20= /cvsroot/emacs/emacs/src/sysdep.c,v=0Aretrieving=20revision=201.245=0A= diff=20-u=20-d=20-b=20-w=20-r1.245=20sysdep.c=0A---=20src/sysdep.c=0922=20= Nov=202002=2012:22:43=20-0000=091.245=0A+++=20src/sysdep.c=094=20Dec=20= 2002=2017:52:59=20-0000=0A@@=20-69,6=20+69,10=20@@=0A=20#endif=0A=20= #endif=20/*=20not=20WINDOWSNT=20*/=0A=20=0A+#ifdef=20HAVE_CARBON=0A= +#define=20read=20sys_read=0A+#endif=0A+=0A=20/*=20Does=20anyone=20other=20= than=20VMS=20need=20this?=20*/=0A=20#ifndef=20fwrite=0A=20#define=20= sys_fwrite=20fwrite=0AIndex:=20src/macterm.c=0A= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0ARCS=20file:=20= /cvsroot/emacs/emacs/src/macterm.c,v=0Aretrieving=20revision=201.26=0A= diff=20-u=20-d=20-b=20-w=20-r1.26=20macterm.c=0A---=20src/macterm.c=092=20= Dec=202002=2017:13:45=20-0000=091.26=0A+++=20src/macterm.c=094=20Dec=20= 2002=2017:53:02=20-0000=0A@@=20-12630,7=20+12630,7=20@@=0A=20=09=09=09=09= expected=0A=20=09=09=09=09?=20TicksToEventTime=20(app_sleep_time)=0A=20=09= =09=09=09:=200,=0A-=09=09=09=09true,=20&eventRef);=0A+=09=09=09=09= kEventRemoveFromQueue,=20&eventRef);=0A=20=20=20if=20(!rneResult)=0A=20=20= =20=20=20{=0A=20=20=20=20=20=20=20/*=20Handle=20new=20events=20*/=0A@@=20= -13446,6=20+13446,60=20@@=0A=20=0C=0A=20#ifdef=20MAC_OSX=0A=20void=0A= +mac_check_bundle()=0A+{=0A+=20=20extern=20int=20inhibit_window_system;=0A= +=20=20extern=20int=20noninteractive;=0A+=20=20CFBundleRef=20appsBundle;=0A= +=20=20pid_t=20child;=0A+=0A+=20=20/*=20No=20need=20to=20test=20if=20= already=20-nw*/=0A+=20=20if=20(inhibit_window_system=20||=20= noninteractive)=0A+=20=20=20=20return;=0A+=0A+=20=20appsBundle=20=3D=20= CFBundleGetMainBundle();=0A+=20=20if=20(appsBundle=20!=3D=20NULL)=0A+=20=20= =20=20{=0A+=20=20=20=20=20=20CFStringRef=20cfBI=20=3D=20= CFSTR("CFBundleIdentifier");=0A+=20=20=20=20=20=20CFTypeRef=20res=20=3D=20= CFBundleGetValueForInfoDictionaryKey(appsBundle,=20cfBI);=0A+=20=20=20=20= =20=20/*=20We=20found=20the=20bundle=20identifier,=20now=20we=20know=20= we=20are=20valid.=20*/=0A+=20=20=20=20=20=20if=20(res=20!=3D=20NULL)=0A+=09= {=0A+=09=20=20CFRelease(res);=0A+=09=20=20return;=0A+=09}=0A+=20=20=20=20= }=0A+=0A+=20=20/*=20Now=20we=20must=20find=20the=20"bundled"=20= executable=20and=20exec=20it=20*/=0A+=20=20child=20=3D=20fork();=0A+=20=20= if=20(child=20<=200)=20=0A+=20=20=20=20{=0A+=20=20=20=20=20=20/*=20If=20= there=20is=20an=20error,=20try=20to=20keep=20going=20inside=20the=20= terminal=20*/=0A+=20=20=20=20=20=20inhibit_window_system=20=3D=201;=0A+=20= =20=20=20}=0A+=20=20if=20(!child)=20=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= int=20i;=0A+=20=20=20=20=20=20extern=20char=20**initial_argv;=0A+=20=20=20= =20=20=20extern=20int=20initial_argc;=0A+=20=20=20=20=20=20char=20= *newApp=20=3D=20"/Applications/Emacs.app/Contents/MacOS/Emacs";=0A+=20=20= =20=20=20=20register=20const=20unsigned=20char=20**new_argv=20=3D=0A+=09= (const=20unsigned=20char=20**)=20alloca=20((initial_argc+1)=20*=20= sizeof(char*));=0A+=20=20=20=20=20=20new_argv[0]=20=3D=20newApp;=0A+=20=20= =20=20=20=20for=20(i=20=3D=201;=20i=20<=20initial_argc;=20i++)=20=0A+=09= new_argv[i]=20=3D=20initial_argv[i];=0A+=20=20=20=20=20=20= new_argv[initial_argc]=3DNULL;=20=20/*=20Will=20point=20to=20last=20= entry*/=0A+=20=20=20=20=20=20execv(newApp,=20new_argv);=0A+=20=20=20=20=20= =20_exit(-1);=0A+=20=20=20=20}=20=0A+=20=20else=0A+=20=20=20=20{=0A+=20=20= =20=20=20=20/*=20Started=20successfully=20*/=0A+=20=20=20=20=20=20= exit(0);=0A+=20=20=20=20}=0A+}=0A+=0A+void=0A=20MakeMeTheFrontProcess=20= ()=0A=20{=0A=20=20=20ProcessSerialNumber=20psn;=0A@@=20-13454,6=20= +13508,195=20@@=0A=20=20=20err=20=3D=20GetCurrentProcess=20(&psn);=0A=20=20= =20if=20(err=20=3D=3D=20noErr)=0A=20=20=20=20=20(void)=20SetFrontProcess=20= (&psn);=0A+}=0A+=0A+/*=20Fix=20C-g=20hang=20in=20emacs=20by=20placing=20= blocking=20IO=20in=20separate=20thread.=20=20*/=0A+#define=20= kEventClassEmacs=20'EMAx'=0A+#define=20kEventEmacsReadDone=20'read'=0A= +#define=20kEventParamErrorNo=20'errn'=0A+MPQueueID=20reader_queue=20=3D=20= NULL;=0A+pthread_t=20mac_reader_thread=20=3D=20NULL;=0A+=0A+void=20=0A= +mac_reader_loop=20(void=20*arg)=0A+{=0A+=20=20sigset_t=20sigs;=0A+=20=20= sigfillset(&sigs);=0A+=20=20sigdelset(&sigs,=20SIGINT);=0A+=20=20= sigdelset(&sigs,=20SIGURG);=0A+=20=20pthread_sigmask(SIG_SETMASK,=20= &sigs,=20NULL);=0A+=20=20while=20(1)=20=0A+=20=20=20=20{=0A+=20=20=20=20=20= =20int=20fildes;=0A+=20=20=20=20=20=20char=20*buf;=0A+=20=20=20=20=20=20= unsigned=20int=20nbyte;=0A+=20=20=20=20=20=20ssize_t=20result;=0A+=20=20=20= =20=20=20int=20curerr=20=3D=200;=0A+=20=20=20=20=20=20EventRef=20event;=0A= +=0A+=20=20=20=20=20=20MPWaitOnQueue(reader_queue,=20(void**)&fildes,=20= (void**)&buf,=20(void**)&nbyte,=20kDurationForever);=0A+=20=20=20=20=20=20= result=20=3D=20read(fildes,=20buf,=20nbyte);=20=20=20=0A+=20=20=20=20=20=20= if=20(result=20<=200)=0A+=09curerr=20=3D=20errno;=0A+=0A+=20=20=20=20=20=20= CreateEvent(NULL,=20kEventClassEmacs,=20kEventEmacsReadDone,=0A+=09=09=20= =200,=20kEventAttributeUserEvent,=20&event);=0A+=20=20=20=20=20=20= SetEventParameter(event,=20kEventParamDirectObject,=20typeUInt32,=20=0A+=09= =09=09sizeof(UInt32),=20&result);=0A+=20=20=20=20=20=20= SetEventParameter(event,=20kEventParamErrorNo,=20typeUInt32,=20=0A+=09=09= =09sizeof(UInt32),=20&curerr);=0A+=20=20=20=20=20=20= PostEventToQueue(GetMainEventQueue(),=20event,=0A+=09=09=20=20=20=20=20=20= =20kEventPriorityHigh);=0A+=20=20=20=20=20=20ReleaseEvent(event);=0A+=0A= +=20=20=20=20=20=20/*=20Post=20any=20stolen=20events=20back=20to=20the=20= event=20queue=20at=20once=20*/=0A+=20=20=20=20}=0A+}=0A+=0A+UInt32=20= mac_quit_char_keycode;=0A+UInt32=20mac_quit_char_modifiers;=0A+#define=20= kModifierMask=20(controlKey|cmdKey|optionKey|shiftKey)=0A+=0A+static=20= OSStatus=0A+mac_register_quit_char()=0A+{=0A+=20=20UInt32=20modifiers=20= =3D=20ctrl_modifier;=0A+=20=20mac_quit_char_modifiers=20=3D=200;=0A+=20=20= mac_quit_char_keycode=20=3D=200x05;=20=20=0A+=20=20/*=20FIXME:=20if=20= quit_char=20is=20not=20C-g,=20then=20we=20need=20to=20map=20from=20=0A+=20= =20=20=20=20ascii=20to=20keyCode.=20=20Look=20at=20= =20for=20details=20*/=0A+=20=20= /*http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184= */=0A+=20=20=0A+=20=20/*=20Map=20modifiers=20*/=0A+=20=20if=20(modifiers=20= &=20ctrl_modifier)=20=20mac_quit_char_modifiers=20|=3D=20macCtrlKey;=0A+=20= =20if=20(modifiers=20&=20shift_modifier)=20mac_quit_char_modifiers=20|=3D=20= macShiftKey;=0A+=20=20if=20(modifiers=20&=20meta_modifier)=20=20= mac_quit_char_modifiers=20|=3D=20macMetaKey;=0A+=20=20if=20(modifiers=20= &=20alt_modifier)=20=20=20mac_quit_char_modifiers=20|=3D=20macAltKey;=0A= +}=0A+=0A+static=20void=0A+initialize_reader_thread()=0A+{=0A+=20=20if=20= (!mac_reader_thread)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20int=20result;=0A= +=20=20=20=20=20=20mac_register_quit_char();=0A+=20=20=20=20=20=20= MPCreateQueue(&reader_queue);=0A+=20=20=20=20=20=20if=20= (!pthread_create(&mac_reader_thread,=20NULL,=20mac_reader_loop,=20NULL))=0A= +=09{=0A+=09=20=20/*=20For=20some=20reason=20pthread_create=20is=20= working,=20but=20returning=20200.=20*/=0A+=09}=0A+=20=20=20=20}=0A+}=0A+=0A= +static=20UInt32=0A+mac_blocked_io_call()=0A+{=0A+=20=20UInt32=20result;=0A= +=20=20EventRef=20event;=0A+=20=20OSStatus=20err;=0A+=0A+=20=20static=20= EventTypeSpec=20mac_reader_events[]=20=3D=20{=0A+=20=20=20=20= {kEventClassKeyboard,=20kEventRawKeyUp},=20/*=20See=20note=20below*/=0A+=20= =20=20=20{kEventClassEmacs,=20kEventEmacsReadDone}=0A+=20=20};=0A+=0A+=20= =20/*=20This=20relies=20on=20the=20fact=20that=20keyUp=20events=20are=20= ignored=20by=20emacs,=0A+=20=20=20and=20are,=20in=20general,=20ignored=20= by=20everything=20else.=20=20This=20means=20we=0A+=20=20=20can=20suck=20= all=20the=20events=20off=20the=20queue=20and=20remain=20in=20a=20wait=20= state.=0A+=20=20=20Using=20keydown=20causes=20issues=20because=20you=20= cannot=20leave=20the=20event=20on=20=0A+=20=20=20the=20queue,=20or=20= this=20call=20will=20be=20constantly=20called=20with=20that=20event.=0A+=20= =20=20So=20to=20use=20keydown,=20you=20must=20either=20save=20the=20= event=20for=20posting=20later=0A+=20=20=20or=20generate=20the=20= input_event=20here.=20=20Generating=20the=20input_event=20is=0A+=20=20=20= probably=20better.=0A+=0A+=20=20=20The=20switch=20to=20keyDown=20should=20= be=20made=20to=20make=20the=20behavior=20uniform=0A+=20=20=20across=20= platforms,=20but=20this=20would=20require=20splitting=20up=20= XTread_socket.=0A+=20=20=20Hopefully,=20then=20the=20event=20handling=20= will=20be=20split=20into=20a=20separate=20file.=0A+=20=20=20Using=20= standard=20carbon=20event=20handlers=20with=20the=20= kbd_buffer_store_event=0A+=20=20=20code=20would=20probably=20be=20best.=0A= +=20=20*/=0A+=20=20while=20(1)=20=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= err=20=3D=20ReceiveNextEvent(2,=20mac_reader_events,=20= kEventDurationForever,=0A+=09=09=09=20=20=20=20=20kEventRemoveFromQueue,=20= &event);=0A+=20=20=20=20=20=20if=20(err=20!=3D=20noErr)=20=0A+=09= fprintf(stderr,=20"Got=20Error=20in=20RNE:=20%d",=20err);=0A+=20=20=20=20= =20=20UInt32=20eClass=20=3D=20GetEventClass(event);=0A+=20=20=20=20=20=20= if=20(eClass=20=3D=3D=20kEventClassEmacs)=20=0A+=09{=0A+=09=20=20int=20= threadErrno=20=3D=200;=0A+=09=20=20err=20=3D=20GetEventParameter=20= (event,=20kEventParamDirectObject,=20typeUInt32,=0A+=09=09=09=09=20=20=20= NULL,=20sizeof(UInt32),=20NULL,=20&result);=0A+=09=20=20if=20(err=20!=3D=20= noErr)=20=0A+=09=20=20=20=20fprintf(stderr,=20"Got=20Error=20in=20RNE:=20= %d",=20err);=0A+=09=20=20/*=20Need=20to=20get=20errno=20from=20read=20= thread=20to=20main=20thread=20here.=20*/=0A+=09=20=20err=20=3D=20= GetEventParameter=20(event,=20kEventParamErrorNo,=20typeUInt32,=0A+=09=09= =09=09=20=20=20NULL,=20sizeof(UInt32),=20NULL,=20&threadErrno);=0A+=09=20= =20if=20(err=20!=3D=20noErr)=20=0A+=09=20=20=20=20fprintf(stderr,=20"Got=20= Error=20in=20RNE:=20%d",=20err);=0A+=09=20=20errno=20=3D=20threadErrno;=0A= +=09=20=20break;=0A+=09}=0A+=20=20=20=20=20=20else=20=0A+=09{=0A+=09=20=20= UInt32=20keyCode,=20modifiers;=0A+=09=20=20GetEventParameter(event,=20= kEventParamKeyCode,=20typeUInt32,=20NULL,=0A+=09=09=09=20=20=20=20= sizeof(UInt32),=20NULL,=20&keyCode);=0A+=09=20=20if=20(keyCode=20=3D=3D=20= mac_quit_char_keycode)=0A+=09=20=20=20=20{=0A+=09=20=20=20=20=20=20= GetEventParameter(event,=20kEventParamKeyModifiers,=20typeUInt32,=0A+=09=09= =09=09NULL,=20sizeof(UInt32),=20NULL,=20&modifiers);=0A+=09=20=20=20=20=20= =20if=20((modifiers=20&=20kModifierMask)=20=3D=3D=20= mac_quit_char_modifiers)=20=0A+=09=09{=0A+=09=09=20=20/*=20Signal=20the=20= read=20to=20stop=20*/=0A+=09=09=20=20pthread_kill(mac_reader_thread,=20= SIGURG);=20=0A+=0A+=09=09=20=20/*=20Instead=20of=20signalling=20= directly,=20possibly=20use=20=0A+=09=09=20=20=20=20=20= kbd_buffer_store_event=20with=20a=20quit_char=20event.=20=20*/=0A+=09=09=20= =20Fsignal=20(Qquit,=20Qnil);=09=09=20=20=0A+=09=09=20=20/*=20NOTREACHED=20= */=0A+=09=09=20=20result=20=3D=20-1;=0A+=09=09}=0A+=09=20=20=20=20}=0A+=09= }=0A+=20=20=20=20}=0A+=20=20ReleaseEvent(event);=0A+=20=20return=20= result;=0A+}=0A+=0A+int=0A+sys_read=20(fildes,=20buf,=20nbyte)=0A+=20=20=20= =20=20int=20fildes;=0A+=20=20=20=20=20char=20*buf;=0A+=20=20=20=20=20= unsigned=20int=20nbyte;=0A+{=0A+#if=20!USE_CARBON_EVENTS=0A+=20=20return=20= read(fildes,=20buf,=20nbyte);=0A+#endif=0A+=0A+=20=20/*=20If=20not=20= GUI,=20use=20default=20behavior=20*/=0A+=0A+=20=20if=20= (inhibit_window_system=20||=20noninteractive)=0A+=20=20=20=20return=20= read(fildes,=20buf,=20nbyte);=0A+=0A+=20=20/*=20Only=20use=20on=20sync=20= threaded=20read=20on=20blocking=20pipes=20and=20sockets=20*/=0A+=20=20{=0A= +=20=20=20=20struct=20stat=20stat;=0A+=20=20=20=20fstat(fildes,=20= &stat);=0A+=20=20=20=20if=20(!S_ISFIFO(stat.st_mode)=20||=20= fcntl(fildes,=20F_GETFL,=200)=20&=20O_NONBLOCK)=0A+=20=20=20=20=20=20= return=20read(fildes,=20buf,=20nbyte);=0A+=20=20}=0A+=0A+=20=20= initialize_reader_thread();=0A+=0A+=20=20MPNotifyQueue(reader_queue,=20= (void*)fildes,=20buf,=20(void*)nbyte);=0A+=0A+=20=20{=0A+=20=20=20=20int=20= result;=0A+=20=20=20=20result=20=3D=20mac_blocked_io_call();=0A+=20=20=20= =20return=20result;=0A+=20=20}=0A=20}=0A=20#endif=20/*=20MAC_OSX=20*/=0A=20= =0A= --Apple-Mail-7-588428640 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed 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. --Apple-Mail-7-588428640--