VirtualBox

source: vbox/trunk/src/VBox/Runtime/VBox/RTAssertShouldPanic-vbox.cpp@ 76527

Last change on this file since 76527 was 76452, checked in by vboxsync, 6 years ago

IPRT: Ran scm --fix-err-h. bugref:9344

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.4 KB
Line 
1/* $Id: RTAssertShouldPanic-vbox.cpp 76452 2018-12-25 01:41:25Z vboxsync $ */
2/** @file
3 * IPRT - Assertions, generic RTAssertShouldPanic.
4 */
5
6/*
7 * Copyright (C) 2006-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/assert.h>
32#include <iprt/env.h>
33#include <iprt/errcore.h>
34#include <iprt/string.h>
35
36/** @def VBOX_RTASSERT_WITH_GDB
37 * Enables the 'gdb' VBOX_ASSERT option.
38 */
39#if defined(DOXYGEN_RUNNING) \
40 || ( !defined(VBOX_RTASSERT_WITH_GDB) \
41 && !defined(IN_GUEST) \
42 && !defined(RT_OS_OS2) \
43 && !defined(RT_OS_WINDOWS))
44# define VBOX_RTASSERT_WITH_GDB
45#endif
46
47/** @def VBOX_RTASSERT_WITH_WAIT
48 * Enables the 'wait' VBOX_ASSERT option.
49 */
50#if defined(DOXYGEN_RUNNING) \
51 || ( !defined(VBOX_RTASSERT_WITH_WAIT) \
52 && defined(IN_RING3) \
53 && !defined(RT_OS_OS2) \
54 && !defined(RT_OS_WINDOWS))
55# define VBOX_RTASSERT_WITH_WAIT
56#endif
57
58#ifdef VBOX_RTASSERT_WITH_GDB
59# include <iprt/process.h>
60# include <iprt/path.h>
61# include <iprt/thread.h>
62# include <iprt/asm.h>
63#endif
64
65#ifdef VBOX_RTASSERT_WITH_WAIT
66# include <signal.h>
67# include <unistd.h>
68#endif
69
70/**
71 * Worker that we can wrap with error variable saving and restoring.
72 */
73static bool rtAssertShouldPanicWorker(void)
74{
75 /*
76 * Check for the VBOX_ASSERT variable.
77 */
78 const char *psz = RTEnvGet("VBOX_ASSERT");
79
80 /* not defined => default behaviour. */
81 if (!psz)
82 return true;
83
84 /* 'breakpoint' or 'panic' means default behaviour. */
85 if (!strcmp(psz, "breakpoint") || !strcmp(psz, "panic"))
86 return true;
87
88 /* 'disabled' does not trigger a breakpoint. */
89 if (!strcmp(psz, "disabled"))
90 return false;
91
92#ifdef VBOX_RTASSERT_WITH_WAIT
93 /* 'wait' - execute a sigwait(3) while a debugger is attached. */
94 if (!strcmp(psz, "wait"))
95 {
96 sigset_t signalMask, oldMask;
97 int iSignal;
98 static pid_t lastPid = -1;
99
100 /* Only wait on the first assertion we hit per process fork, assuming
101 * the user will attach the debugger at once if they want to do so.
102 * For a clever solution to detect an attached debugger, see:
103 * http://stackoverflow.com/a/8135517
104 * For now I preferred to keep things simple and hopefully reliable. */
105 if (lastPid == getpid())
106 return true;
107 lastPid = getpid();
108 /* Register signal that we are waiting for */
109 sigemptyset(&signalMask);
110 sigaddset(&signalMask, SIGUSR2);
111 RTAssertMsg2("Attach debugger (pid: %ld) and resume with SIGUSR2.\n", (long)lastPid);
112 pthread_sigmask(SIG_BLOCK, &signalMask, &oldMask);
113 /* Ignoring return status */
114 sigwait(&signalMask, &iSignal);
115 pthread_sigmask(SIG_SETMASK, &oldMask, NULL);
116 /* Breakpoint no longer needed. */
117 return false;
118 }
119#endif
120
121#ifdef VBOX_RTASSERT_WITH_GDB
122 /* 'gdb' - means try launch a gdb session in xterm. */
123 if (!strcmp(psz, "gdb"))
124 {
125 /* Did we already fire up gdb? If so, just hit the breakpoint. */
126 static bool volatile s_fAlreadyLaunchedGdb = false;
127 if (ASMAtomicUoReadBool(&s_fAlreadyLaunchedGdb))
128 return true;
129
130 /* Try find a suitable terminal program. */
131 const char *pszTerm = RTEnvGet("VBOX_ASSERT_TERM");
132 if ( !pszTerm
133 || !RTPathExists(pszTerm))
134 {
135 pszTerm = "/usr/bin/gnome-terminal";
136 if (!RTPathExists(pszTerm))
137 {
138 pszTerm = "/usr/X11R6/bin/xterm";
139 if (!RTPathExists(pszTerm))
140 {
141 pszTerm ="/usr/bin/xterm";
142 if (!RTPathExists(pszTerm))
143 return true;
144 }
145 }
146 }
147
148 /* And find gdb. */
149 const char *pszGdb = RTEnvGet("VBOX_ASSERT_GDB");
150 if ( !pszGdb
151 || !RTPathExists(pszGdb))
152 {
153 pszGdb = "/usr/bin/gdb";
154 if (!RTPathExists(pszGdb))
155 pszGdb = "gdb";
156 }
157
158 /* Try spawn the process. */
159 char szCmd[512];
160 size_t cch = RTStrPrintf(szCmd, sizeof(szCmd), "%s -p %d ", pszGdb, RTProcSelf());
161 if (cch < sizeof(szCmd))
162 {
163 char *pszExecName = &szCmd[cch];
164 if (!RTProcGetExecutablePath(pszExecName, sizeof(szCmd) - cch))
165 *pszExecName = '\0';
166 }
167 const char *apszArgs[] =
168 {
169 pszTerm,
170 "-e",
171 szCmd,
172 NULL
173 };
174 RTPROCESS Process;
175 int rc = RTProcCreate(apszArgs[0], &apszArgs[0], RTENV_DEFAULT, 0, &Process);
176 if (RT_FAILURE(rc))
177 return false;
178
179 ASMAtomicWriteBool(&s_fAlreadyLaunchedGdb, true);
180
181 /* Wait for gdb to attach. */
182 RTThreadSleep(15000);
183 return true;
184 }
185#endif
186
187 /* '*' - don't hit the breakpoint. */
188 return false;
189}
190
191
192RTDECL(bool) RTAssertShouldPanic(void)
193{
194 /*
195 * Check if panicing is excluded by the RTAssert settings first.
196 */
197 if (!RTAssertMayPanic())
198 return false;
199
200 /*
201 * Preserve error state variables.
202 */
203 RTERRVARS SavedErrVars;
204 RTErrVarsSave(&SavedErrVars);
205
206 bool fRc = rtAssertShouldPanicWorker();
207
208 RTErrVarsRestore(&SavedErrVars);
209 return fRc;
210}
211
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette