Esempio n. 1
0
/*
 * Once dication has happened this fires, for better or worse
 */
static void voice_callback(DictationSession *session, DictationSessionStatus status, char *transcription, void *context) {
  
  // If for worse then this is where we go
  if (status != DictationSessionStatusSuccess) {
    LOG_WARN("dictation failed");
    dictation_session_stop(session);
    voice_system_active = false;
    respond_with_vibe(false);
    show_notice(status == DictationSessionStatusFailureTranscriptionRejected ? RESOURCE_ID_NOTICE_VOICE_STOPPED : RESOURCE_ID_NOTICE_VOICE_FAILED);
    return;
  } 
  
  // If we were lucky then we try to match the transcription to a menu item
  dictation_session_stop(session);
  
  LOG_INFO("dictation got %s", transcription);
  bool vibe;
  VoiceSelectAction action = determine_action(transcription, &vibe);
  
  // Allow comms and notices
  voice_system_active = false; 
  
  if (action != NULL) {
    // If we get a match then fire the action
    if (vibe)
      respond_with_vibe(true);
    action();
  } else {
    // Feedback we didn't find anything
    respond_with_vibe(false);
    show_notice_with_message(RESOURCE_ID_VOICE_DIDNT_UNDERSTAND, transcription);
  }
}
Esempio n. 2
0
// The stack-unwinding loop.
static inline void unwind_loop(ExcInfo* exc_data) {
    // NB. https://monoinfinito.wordpress.com/series/exception-handling-in-c/ is a very useful resource
    // as are http://www.airs.com/blog/archives/460 and http://www.airs.com/blog/archives/464
    unw_cursor_t cursor;
    unw_context_t uc; // exists only to initialize cursor
#ifndef NDEBUG
    // poison stack memory. have had problems with these structures being insufficiently initialized.
    memset(&uc, 0xef, sizeof uc);
    memset(&cursor, 0xef, sizeof cursor);
#endif
    unw_getcontext(&uc);
    unw_init_local(&cursor, &uc);

    auto unwind_session = getActivePythonUnwindSession();

    while (unw_step(&cursor) > 0) {
        unw_proc_info_t pip;

        static StatCounter frames_unwound("num_frames_unwound_cxx");
        frames_unwound.log();

        // NB. unw_get_proc_info is slow; a significant chunk of all time spent unwinding is spent here.
        check(unw_get_proc_info(&cursor, &pip));

        assert((pip.lsda == 0) == (pip.handler == 0));
        assert(pip.flags == 0);

        if (VERBOSITY("cxx_unwind") >= 4) {
            print_frame(&cursor, &pip);
        }

        // let the PythonUnwindSession know that we're in a new frame,
        // giving it a chance to possibly add a traceback entry for
        // it.
        unwindingThroughFrame(unwind_session, &cursor);

        // Skip frames without handlers
        if (pip.handler == 0) {
            continue;
        }

        RELEASE_ASSERT(pip.handler == (uintptr_t)__gxx_personality_v0,
                       "personality function other than __gxx_personality_v0; "
                       "don't know how to unwind through non-C++ functions");

        // Don't call __gxx_personality_v0; we perform dispatch ourselves.
        // 1. parse LSDA header
        lsda_info_t info;
        parse_lsda_header(&pip, &info);

        call_site_entry_t entry;
        {
            // 2. Find our current IP in the call site table.
            unw_word_t ip;
            unw_get_reg(&cursor, UNW_REG_IP, &ip);
            // ip points to the instruction *after* the instruction that caused the error - which is generally (always?)
            // a call instruction - UNLESS we're in a signal frame, in which case it points at the instruction that
            // caused the error. For now, we assume we're never in a signal frame. So, we decrement it by one.
            //
            // TODO: double-check that we never hit a signal frame.
            --ip;

            bool found = find_call_site_entry(&info, (const uint8_t*)ip, &entry);
            // If we didn't find an entry, an exception happened somewhere exceptions should never happen; terminate
            // immediately.
            if (!found) {
                panic();
            }
        }

        // 3. Figure out what to do based on the call site entry.
        if (!entry.landing_pad) {
            // No landing pad means no exception handling or cleanup; keep unwinding!
            continue;
        }
        // After this point we are guaranteed to resume something rather than unwinding further.

        if (VERBOSITY("cxx_unwind") >= 4) {
            print_lsda(&info);
        }

        int64_t switch_value = determine_action(&info, &entry);
        if (switch_value != CLEANUP_ACTION) {
            // we're transfering control to a non-cleanup landing pad.
            // i.e. a catch block.  thus ends our unwind session.
            endPythonUnwindSession(unwind_session);
#if STAT_TIMERS
            pyston::StatTimer::finishOverride();
#endif
        }
        static_assert(THREADING_USE_GIL, "have to make the unwind session usage in this file thread safe!");
        // there is a python unwinding implementation detail leaked
        // here - that the unwind session can be ended but its
        // exception storage is still around.
        //
        // this manifests itself as this short window here where we've
        // (possibly) ended the unwind session above but we still need
        // to pass exc_data (which is the exceptionStorage for this
        // unwind session) to resume().
        //
        // the only way this could bite us is if we somehow clobber
        // the PythonUnwindSession's storage, or cause a GC to occur, before
        // transfering control to the landing pad in resume().
        //
        resume(&cursor, entry.landing_pad, switch_value, exc_data);
    }

    // Hit end of stack! return & let unwindException determine what to do.
}