Changeset 5614


Ignore:
Timestamp:
Dec 14, 2006, 2:50:02 PM (18 years ago)
Author:
Gary Byers
Message:

Go back to using the pseudo_sigreturn mechanism on Darwin, since
doing a real sigreturn from a fake context may not be reliable.

When handling an interrupt with a partially created temp stack
frame, do the right thing. (That basically means reset the
frame before calling out and recreating it if we return from the
callout.)

Handle SIGQUIT on the altstack, to provide a way of forcibly
terminating threads that's a bit more GC-safe than doing it
via #_pthread_cancel.

Note the tcr of the gc thread on gc entry; if an exception
happens in that thread, print a message and sleep for 60
seconds.

Note that there's still a race condition here: if thread A
gets an exception and thread B gets the mach_exception_lock
(to GC) before the exception thread can handle the message,
we deadlock (thread A would be suspended in the kernel and
can't respond to a suspend signal.) We can tell that this
has happened and make a good guess as to why it happened,
but dealing with it will require some thought. (If we've
already issued a suspend signal and eventually raise the
suspended thread's resume semaphore, it'll suspend and resume
once the mach exception thread makes it runnable. Who
cleans up its exception context in that case ? Does it
matter ?)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/lisp-kernel/x86-exceptions.c

    r5550 r5614  
    3232#include <linux/prctl.h>
    3333#endif
     34#ifdef DARWIN
     35#include <sysexits.h>
     36#endif
     37#include <sys/syslog.h>
     38
    3439
    3540int
     
    877882  }
    878883  unlock_exception_lock_in_handler(tcr);
     884#ifndef DARWIN_USE_PSEUDO_SIGRETURN
    879885  exit_signal_handler(tcr, old_valence);
     886#endif
    880887  /* raise_pending_interrupt(tcr); */
    881888#ifdef DARWIN_GS_HACK
     
    884891  }
    885892#endif
     893#ifndef DARWIN_USE_PSEUDO_SIGRETURN
    886894  SIGRETURN(context);
     895#endif
    887896}
    888897
     
    10581067          int old_valence;
    10591068          signed_natural alloc_displacement = 0;
    1060          
     1069          LispObj
     1070            *next_tsp = tcr->next_tsp,
     1071            *save_tsp = tcr->save_tsp,
     1072            *p,
     1073            q;
     1074           
     1075          if (next_tsp != save_tsp) {
     1076            tcr->next_tsp = save_tsp;
     1077          } else {
     1078            next_tsp = NULL;
     1079          }
    10611080          pc_luser_xp(context, tcr, &alloc_displacement);
    10621081          old_valence = prepare_to_wait_for_exception_lock(tcr, context);
     
    10651084          if (alloc_displacement) {
    10661085            tcr->save_allocptr -= alloc_displacement;
     1086          }
     1087          if (next_tsp) {
     1088            tcr->next_tsp = next_tsp;
     1089            p = next_tsp;
     1090            while (p != save_tsp) {
     1091              *p++ = 0;
     1092            }
     1093            q = (LispObj)save_tsp;
     1094            *next_tsp = q;
    10671095          }
    10681096          unlock_exception_lock_in_handler(tcr);
     
    12171245
    12181246void
     1247quit_handler(int signum, siginfo_t info, ExceptionInformation *xp)
     1248{
     1249  TCR *tcr = get_tcr(false);
     1250  area *a;
     1251  sigset_t mask;
     1252 
     1253  sigemptyset(&mask);
     1254
     1255
     1256  if (tcr) {
     1257    tcr->valence = TCR_STATE_FOREIGN;
     1258    a = tcr->vs_area;
     1259    if (a) {
     1260      a->active = a->high;
     1261    }
     1262    a = tcr->ts_area;
     1263    if (a) {
     1264      a->active = a->high;
     1265    }
     1266    a = tcr->cs_area;
     1267    if (a) {
     1268      a->active = a->high;
     1269    }
     1270  }
     1271 
     1272  pthread_sigmask(SIG_SETMASK,&mask,NULL);
     1273  pthread_exit(NULL);
     1274}
     1275
     1276void
     1277altstack_quit_handler(int signum, siginfo_t *info, ExceptionInformation *context)
     1278{
     1279#ifdef DARWIN_GS_HACK
     1280  Boolean gs_was_tcr = ensure_gs_pthread();
     1281#endif
     1282  TCR* tcr = get_tcr(true);
     1283  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
     1284#ifdef LINUX
     1285  fpregset_t fpregs = NULL;
     1286#else
     1287  void *fpregs = NULL;
     1288#endif
     1289#ifdef DARWIN
     1290  MCONTEXT_T mcontextp = NULL;
     1291#endif
     1292
     1293  siginfo_t *info_copy = NULL;
     1294  ExceptionInformation *xp = NULL;
     1295
     1296  if (foreign_rsp) {
     1297#ifdef LINUX
     1298    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
     1299#endif
     1300#ifdef DARWIN
     1301    foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
     1302#endif
     1303    foreign_rsp = copy_siginfo(info, foreign_rsp);
     1304    info_copy = (siginfo_t *)foreign_rsp;
     1305    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
     1306    xp = (ExceptionInformation *)foreign_rsp;
     1307#ifdef DARWIN
     1308    UC_MCONTEXT(xp) = mcontextp;
     1309#endif
     1310    *--foreign_rsp = (LispObj)__builtin_return_address(0);
     1311    switch_to_foreign_stack(foreign_rsp,quit_handler,signum,info_copy,xp);
     1312  }
     1313}
     1314
     1315void
    12191316thread_signal_setup()
    12201317{
     
    12241321  install_signal_handler(thread_suspend_signal, (void *)altstack_suspend_resume_handler);
    12251322  install_signal_handler(thread_resume_signal, (void *)altstack_suspend_resume_handler);
     1323  install_signal_handler(SIGQUIT, (void *)altstack_quit_handler);
    12261324}
    12271325
     
    15231621   function returned */
    15241622
     1623TCR *gc_tcr = NULL;
     1624
    15251625int
    15261626gc_like_from_xp(ExceptionInformation *xp,
     
    15421642    return 0;
    15431643  }
     1644
     1645  gc_tcr = tcr;
    15441646
    15451647  /* This is generally necessary if the current thread invoked the GC
     
    15771679    other_tcr = other_tcr->next;
    15781680  } while (other_tcr != tcr);
     1681
     1682  gc_tcr = NULL;
    15791683
    15801684  resume_other_threads(true);
     
    20082112#else
    20092113#define ts_pc(t) t.eip
     2114#endif
     2115
     2116#ifdef DARWIN_USE_PSEUDO_SIGRETURN
     2117#define DARWIN_EXCEPTION_HANDLER signal_handler
     2118#else
     2119#define DARWIN_EXCEPTION_HANDLER pseudo_signal_handler
    20102120#endif
    20112121
     
    20882198      if (signum) {
    20892199        kret = setup_signal_frame(thread,
    2090                                   (void *)pseudo_signal_handler,
     2200                                  (void *)DARWIN_EXCEPTION_HANDLER,
    20912201                                  signum,
    20922202                                  code,
     
    21072217  } else {
    21082218    SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION);
     2219     
    21092220#if 0
    21102221    fprintf(stderr, "deferring pending exception in 0x%x\n", tcr);
    21112222#endif
    21122223    kret = 0;
     2224    if (tcr == gc_tcr) {
     2225      int i;
     2226      write(1, "exception in GC thread. Sleeping for 60 seconds\n",sizeof("exception in GC thread.  Sleeping for 60 seconds\n"));
     2227      for (i = 0; i < 60; i++) {
     2228        sleep(1);
     2229      }
     2230      _exit(EX_SOFTWARE);
     2231    }
    21132232  }
    21142233  return kret;
     
    21172236
    21182237
     2238
     2239static mach_port_t mach_exception_thread = (mach_port_t)0;
    21192240
    21202241
     
    21292250  mach_port_t p = TCR_TO_EXCEPTION_PORT(arg);
    21302251
     2252  mach_exception_thread = pthread_mach_thread_np(pthread_self());
    21312253  mach_msg_server(exc_server, 256, p, 0);
    21322254  /* Should never return. */
     
    21342256}
    21352257
     2258
     2259
     2260void
     2261mach_exception_thread_shutdown()
     2262{
     2263  kern_return_t kret;
     2264
     2265  fprintf(stderr, "terminating Mach exception thread, 'cause exit can't\n");
     2266  kret = thread_terminate(mach_exception_thread);
     2267  if (kret != KERN_SUCCESS) {
     2268    fprintf(stderr, "Couldn't terminate exception thread, kret = %d\n",kret);
     2269  }
     2270}
    21362271
    21372272
Note: See TracChangeset for help on using the changeset viewer.