Quelles actions dois-je prendre pour obtenir un crash dump dans tous les scénarios d'erreur?

nous sommes sur Windows et nous voulons obtenir un crash dump (peut-être en utilisant MiniDumpWriteDump) scénarios où la sortie de notre application est inattendue.

jusqu'à présent, nous avons identifié et mis en place, les éléments suivants:

  • SetUnhandledExceptionFilter pour une exception non gérée (Win32 ainsi que la "normale" C++.)
  • _set_invalid_parameter_handler pour les CRT argument non valide manipulation
  • _set_abort_behaviorles plus SIGABRT gestionnaire pour tenir compte des appels à abort()

y a-t-il quelque chose qu'on a manqué? (Modulo quelque code appelant non légitimement ExitProcess,TerminateProcess ou un exit variantes.)


je vais noter que cette question ici est orthogonale à comment un crash dump est alors obtenu. Par exemple, si vous voulez un crash dump en cas de abort, vous devez utiliser _set_abort_behaviour parce qu'autrement avorter juste exit.

je vais aussi noter que sur Windows7+, réglage SetUHEF et juste de la configuration de l' "correct" WER paramètres de vidage dans le registre est souvent un moyen viable.

12
demandé sur Martin Ba 2012-11-27 23:11:09

6 réponses

j'utilise exactement ceux que vous avez énumérés, plus _set_purecall_handler, plus ce petit bout de code pratique:

void EnableCrashingOnCrashes()
{
    typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
    typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
    static const DWORD EXCEPTION_SWALLOWING = 0x1;

    const HMODULE kernel32 = LoadLibraryA("kernel32.dll");
    const tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
    const tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
    if(pGetPolicy && pSetPolicy)
    {
        DWORD dwFlags;
        if(pGetPolicy(&dwFlags))
        {
            // Turn off the filter
            pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
        }
    }
}

Source: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/

http://randomascii.wordpress.com/2011/12/07/increased-reliability-through-more-crashes/ http://randomascii.wordpress.com/2012/07/22/more-adventures-in-failing-to-crash-properly/

6
répondu Ben Hymers 2013-08-01 09:20:50

SetUnhandledExceptionFilter n'est absolument pas suffisant pour capturer toutes les sorties inattendues. Si une application appelle accidentellement une fonction virtuelle pure, alors un dialogue apparaîtra. L'application va pendre, mais pas s'écraser. Comme il n'y a pas d'exception, ni Settledexceptionfilter, ni WER ne peuvent aider. Il y a quelques variations sur ce thème.

pire encore est la bizarrerie si vous vous écrasez dans un rappel du noyau tel Qu'un WindowProc. Si cela se produit dans une application 32 bits sur Windows 64 bits alors l'exception est attrapée par le système D'exploitation et l'exécution continue. Oui, l'incident est tendit silencieusement. Je trouve que terrifiant.

http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/ devrait détailler toutes les astuces nécessaires pour traiter ces cas inhabituels.

2
répondu user2681297 2013-08-14 06:51:06

grand ordre, en bref:

  • Vous n'avez pas besoin d'utiliser d'autres _set* fonctions SetUnhandledExceptionFilter est suffisant pour tous.
  • C fonctions d'exécution comme abort va désactiver le gestionnaire d'exception global, que vous configurez en utilisant SetUnhandledExceptionFilter. CRT appellera simplement cette même fonctionNULL paramètre, et à l'exception de gestionnaire est désactivé (pas appelé), si le CRT est à l'origine de crash! Que pouvez-vous faire? [X]
  • Désactiver tous les autres threads en cours d'exécution lorsque le gestionnaire d'excption est appelé. Il suffit de rechercher tous les threads en utilisant CreateToolhelp32Snapshot, et d'autres fonctions. Recherchez ce processus, et suspendez tous les autres threads en cours d'exécution (sauf current, ofcourse).
  • utiliser SEH ou no-SEH, global-exception handler est appelé sauf si CRT interfère. Ne vous inquiétez pas (dans la plupart des cas).
  • Ne pas tout CLR entre-deux, il ne sera pas permettre au gestionnaire d'exception à l'appel, le cas échéant CLR/géré appel (oui à partir de C/C++) entre.
  • vous ne pouvez pas gérer une exception-débordement de la pile! Pensez! Exécuter sous un débogueur n'est qu'une solution, voir ci-dessous.

il y a plus à cela, que je n'ai pas essayé (pas trouvé d'utilité) - la manipulation D'Exception Vectored.

Une autre approche consiste à exécuter l'application dans un débogueur, vous pouvez créer vous-même! Dans le débogueur, vous pouvez attraper toutes les exceptions, tout comme VS debugger attrape. Voir mon article. Mais, vous savez, ce n'est pas la bonne approche.

EDIT: il suffit de lire le dernier contenu à propos de process-termination. Tu ne devrais pas contrôler ça. Dans tous les cas, vous pouvez simplement accrocher les API nécessaires, qui agiraient comme ce que vous codez pour (comme l'affichage de la boîte de message).

[X] vous devez utiliser API hooking. Je n'ai pas de lien et de détails à portée de main. Vous accrocheriez D'autres API connexes, mais principalement le SetUnhandledExceptionFilter (après vous avais appelé pour vous). Votre fonction de mannequin (accroché) aura l'air comme:

xxx SetUnhandledExceptionFilter_DUMMY(xxx)
{
  // Dont do any thing
  return NULL;
}

Je n'ai pas le lien et les détails de connexion API à portée de main.


Et pourquoi ne pas tenter de rendre votre application plus sûre?

  • corriger tous les Avertissements (oui, même le niveau 4).
  • utilisez l'analyse statique. VS lui-même a (dans les versions plus élevées, cependant. Sauf 2012 - toutes les variantes). D'autres outils D'as sont disponibles.
  • faites une révision minutieuse du code. C'est payant!
  • exécuter et déboguer la compilation de votre version le débogueur. Utilisez toutes les fonctionnalités.
  • regarder et corriger toutes les fuites de mémoire possibles.
  • utiliser une approche défensive pour la programmation. Plutôt que de vérifier si null, défendez-le en utilisant ASSERT, ou votre propre assert. Pack avec l'affirmation, de journal, de retour de la fonction.
1
répondu Ajay 2012-11-27 19:49:15

je vais ajouter une solution de contournement que l'on peut utiliser dans certains scénarios quand on exécute Windows 7:

Windows Error Reporting (WER) offre l'option rédiger des vidages de mémoire sur l'app crash.

donc, si vous êtes d'accord avec ça, vous "juste" devez vous assurer que les scénarios de crash qui vous intéressent réellement vont déclencher WER. ... Ce qui nous ramène à cette question, mais quand même ...

0
répondu Martin Ba 2017-05-23 12:15:56

Vous pouvez attraper n'importe quelle exception avec WER. Comme vous l'avez vu, le CRT force parfois à appeler WER.

Si vous voulez toujours prendre excpetion dans le processus, vous devez prévenir l'appel de SetUnhandledExceptionFilter(NULL) à partir de la CRT. Pour plus d'informations, voir mon billet de blog: Amélioration De "PreventSetUnhandledExceptionFilter"

0
répondu Jochen Kalmbach 2013-08-01 07:49:59

Pour développer sur toutes les réponses, voici ce que j'ai trouvé de mieux pour 100M+ installe:

std:: set_terminate et std:: set_unexpected peut-être devrait également être mentionnée.

Et la partie la plus importante pour obtenir tout droit:

  • tous ces gestionnaires devraient appeler une fonction qui s'exécute sous une section mutex / critique pour s'assurer que s'il y a d'autres accidents se produisant dans d'autres en même temps, ils s'arrêtaient et attendaient au lieu de faire des ravages.
  • le gestionnaire de signal pour SIGABRT doit se positionner en arrière comme un gestionnaire de SIGABRT! Sans cela, si vous obtenez des plantages se produisant en même temps à partir d'autres threads que vous traitez va sortir immédiatement sans vous donner le temps de gérer le plantage.
  • traitement de l'erreur, idéalement, devrait arriver dans un autre processus, ou au moins dans un autre thread qui a commencé au début du processus, sinon vous ne serez pas en mesure de gérer les conditions de mémoire faible ou stackoverflow erreurs.

voir setExceptionHandlers ci-dessous pour référence. Aussi, très probablement vous ne voulez pas brancher tous les gestionnaires dans les constructions de debug ou quand IsDebuggerPresent.

#include <signal.h>
#include <windows.h>
#include <boost/thread/mutex.hpp>

void EnableCrashingOnCrashes();
void PreventSetUnhandledExceptionFilter();

static void exceptionHandler(EXCEPTION_POINTERS* excpInfo)
{
    // your code to handle the exception. Ideally it should
    // marshal the exception for processing to some other
    // thread and waif for the thread to complete the job
}

static boost::mutex unhandledExceptionMx;
static LONG WINAPI unhandledException(EXCEPTION_POINTERS* excpInfo = NULL)
{
    boost::mutex::scoped_lock lock(unhandledExceptionMx);
    if (!excpInfo == NULL)
    {
        __try // Generate exception to get proper context in dump
        {
            RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
        }
        __except (exceptionHandler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER)
        {
        }
    }
    else
    {
        exceptionHandler(excpInfo);
    }

    return 0;
}

static void invalidParameter(const wchar_t* expr, const wchar_t* func,
    const wchar_t* file, unsigned int line, uintptr_t reserved)
{
    unhandledException();
}

static void pureVirtualCall()
{
    unhandledException();
}

static void sigAbortHandler(int sig)
{
    // this is required, otherwise if there is another thread
    // simultaneously tries to abort process will be terminated
    signal(SIGABRT, sigAbortHandler);
    unhandledException();
}

static void setExceptionHandlers()
{
    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
    SetUnhandledExceptionFilter(unhandledException);
    _set_invalid_parameter_handler(invalidParameter);
    _set_purecall_handler(pureVirtualCall);
    signal(SIGABRT, sigAbortHandler);
    _set_abort_behavior(0, 0);
    EnableCrashingOnCrashes();
    PreventSetUnhandledExceptionFilter();
}
0
répondu Pavel 2018-02-15 23:14:44