/[pcsx2_0.9.7]/trunk/common/src/Utilities/Exceptions.cpp
ViewVC logotype

Contents of /trunk/common/src/Utilities/Exceptions.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 1 month ago) by william
File size: 13471 byte(s)
re-commit (had local access denied errors when committing)
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17
18 #include <wx/app.h>
19 #include "Threading.h"
20 #include "TlsVariable.inl"
21
22 #if defined(__UNIX__)
23 #include <signal.h>
24 #endif
25
26 // for lack of a better place...
27 Fnptr_OutOfMemory pxDoOutOfMemory = NULL;
28
29 static wxString GetTranslation( const wxChar* msg )
30 {
31 return msg ? wxGetTranslation( msg ) : wxEmptyString;
32 }
33
34 // ------------------------------------------------------------------------
35 // Force DevAssert to *not* inline for devel builds (allows using breakpoints to trap assertions,
36 // and force it to inline for release builds (optimizes it out completely since IsDevBuild is a
37 // const false).
38 //
39 #ifdef PCSX2_DEVBUILD
40 # define DEVASSERT_INLINE __noinline
41 #else
42 # define DEVASSERT_INLINE __fi
43 #endif
44
45 // Using a threadlocal assertion guard. Separate threads can assert at the same time.
46 // That's ok. What we don't want is the *same* thread recurse-asserting.
47 static DeclareTls(int) s_assert_guard( 0 );
48
49 pxDoAssertFnType* pxDoAssert = pxAssertImpl_LogIt;
50
51 // make life easier for people using VC++ IDE by using this format, which allows double-click
52 // response times from the Output window...
53 wxString DiagnosticOrigin::ToString( const wxChar* msg ) const
54 {
55 FastFormatUnicode message;
56
57 message.Write( L"%s(%d) : assertion failed:\n", srcfile, line );
58
59 if( function != NULL )
60 message.Write( " Function: %s\n", function );
61
62 message.Write(L" Thread: %s\n", Threading::pxGetCurrentThreadName().c_str() );
63
64 if( condition != NULL )
65 message.Write(L" Condition: %s\n", condition);
66
67 if( msg != NULL )
68 message.Write(L" Message: %s\n", msg);
69
70 return message;
71 }
72
73
74 // Because wxTrap isn't available on Linux builds of wxWidgets (non-Debug, typically)
75 void pxTrap()
76 {
77 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
78 __debugbreak();
79 #elif defined(__WXMAC__) && !defined(__DARWIN__)
80 #if __powerc
81 Debugger();
82 #else
83 SysBreak();
84 #endif
85 #elif defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
86 Debugger();
87 #elif defined(__UNIX__)
88 raise(SIGTRAP);
89 #else
90 // TODO
91 #endif // Win/Unix
92 }
93
94
95 bool pxAssertImpl_LogIt( const DiagnosticOrigin& origin, const wxChar *msg )
96 {
97 //wxLogError( L"%s", origin.ToString( msg ).c_str() );
98 wxMessageOutputDebug().Printf( L"%s", origin.ToString( msg ).c_str() );
99 pxTrap();
100 return false;
101 }
102
103
104 DEVASSERT_INLINE void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg )
105 {
106 // Recursion guard: Allow at least one recursive call. This is useful because sometimes
107 // we get meaningless assertions while unwinding stack traces after exceptions have occurred.
108
109 RecursionGuard guard( s_assert_guard );
110 if (guard.Counter > 2) { return wxTrap(); }
111
112 // wxWidgets doesn't come with debug builds on some Linux distros, and other distros make
113 // it difficult to use the debug build (compilation failures). To handle these I've had to
114 // bypass the internal wxWidgets assertion handler entirely, since it may not exist even if
115 // PCSX2 itself is compiled in debug mode (assertions enabled).
116
117 bool trapit;
118
119 if( pxDoAssert == NULL )
120 {
121 // Note: Format uses MSVC's syntax for output window hotlinking.
122 trapit = pxAssertImpl_LogIt( origin, msg );
123 }
124 else
125 {
126 trapit = pxDoAssert( origin, msg );
127 }
128
129 if( trapit ) { pxTrap(); }
130 }
131
132 __fi void pxOnAssert( const DiagnosticOrigin& origin, const char* msg)
133 {
134 pxOnAssert( origin, fromUTF8(msg) );
135 }
136
137
138 // --------------------------------------------------------------------------------------
139 // BaseException (implementations)
140 // --------------------------------------------------------------------------------------
141
142 BaseException::~BaseException() throw() {}
143
144 BaseException& BaseException::SetBothMsgs( const wxChar* msg_diag )
145 {
146 m_message_user = GetTranslation( msg_diag );
147 return SetDiagMsg( msg_diag );
148 }
149
150 BaseException& BaseException::SetDiagMsg( const wxString& msg_diag )
151 {
152 m_message_diag = msg_diag;
153 return *this;
154 }
155
156 BaseException& BaseException::SetUserMsg( const wxString& msg_user )
157 {
158 m_message_user = msg_user;
159 return *this;
160 }
161
162 wxString BaseException::FormatDiagnosticMessage() const
163 {
164 return m_message_diag;
165 }
166
167 wxString BaseException::FormatDisplayMessage() const
168 {
169 return m_message_user.IsEmpty() ? m_message_diag : m_message_user;
170 }
171
172 // --------------------------------------------------------------------------------------
173 // Exception::RuntimeError (implementations)
174 // --------------------------------------------------------------------------------------
175 Exception::RuntimeError::RuntimeError( const std::runtime_error& ex, const wxString& prefix )
176 {
177 IsSilent = false;
178
179 SetDiagMsg( pxsFmt( L"STL Runtime Error%s: %s",
180 (prefix.IsEmpty() ? prefix.c_str() : pxsFmt(L" (%s)", prefix.c_str()).c_str()),
181 fromUTF8( ex.what() ).c_str()
182 ) );
183 }
184
185 Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString& prefix )
186 {
187 IsSilent = false;
188
189 SetDiagMsg( pxsFmt( L"STL Exception%s: %s",
190 (prefix.IsEmpty() ? prefix.c_str() : pxsFmt(L" (%s)", prefix.c_str()).c_str()),
191 fromUTF8( ex.what() ).c_str()
192 ) );
193 }
194
195 // --------------------------------------------------------------------------------------
196 // Exception::OutOfMemory (implementations)
197 // --------------------------------------------------------------------------------------
198 Exception::OutOfMemory::OutOfMemory( const wxString& allocdesc )
199 {
200 AllocDescription = allocdesc;
201 }
202
203 wxString Exception::OutOfMemory::FormatDiagnosticMessage() const
204 {
205 FastFormatUnicode retmsg;
206 retmsg.Write(L"Out of memory");
207 if (!AllocDescription.IsEmpty())
208 retmsg.Write(L" while allocating '%s'", AllocDescription.c_str());
209
210 if (!m_message_diag.IsEmpty())
211 retmsg.Write(L":\n%s", m_message_diag.c_str());
212
213 return retmsg;
214 }
215
216 wxString Exception::OutOfMemory::FormatDisplayMessage() const
217 {
218 FastFormatUnicode retmsg;
219 retmsg.Write( L"%s", _("Oh noes! Out of memory!") );
220
221 if (!m_message_diag.IsEmpty())
222 retmsg.Write(L"\n\n%s", m_message_diag.c_str());
223
224 return retmsg;
225 }
226
227
228 // --------------------------------------------------------------------------------------
229 // Exception::VirtualMemoryMapConflict (implementations)
230 // --------------------------------------------------------------------------------------
231 Exception::VirtualMemoryMapConflict::VirtualMemoryMapConflict( const wxString& allocdesc )
232 {
233 AllocDescription = allocdesc;
234 m_message_user = _("Virtual memory mapping failure! Your system may have conflicting device drivers, services, or may simply have insufficient memory or resources to meet PCSX2's lofty needs.");
235 }
236
237 wxString Exception::VirtualMemoryMapConflict::FormatDiagnosticMessage() const
238 {
239 FastFormatUnicode retmsg;
240 retmsg.Write(L"Virtual memory map failed");
241 if (!AllocDescription.IsEmpty())
242 retmsg.Write(L" while reserving '%s'", AllocDescription.c_str());
243
244 if (!m_message_diag.IsEmpty())
245 retmsg.Write(L":\n%s", m_message_diag.c_str());
246
247 return retmsg;
248 }
249
250 wxString Exception::VirtualMemoryMapConflict::FormatDisplayMessage() const
251 {
252 FastFormatUnicode retmsg;
253 retmsg.Write( L"%s",
254 pxE( "!Notice:VirtualMemoryMap",
255 L"There is not enough virtual memory available, or necessary virtual memory "
256 L"mappings have already been reserved by other processes, services, or DLLs."
257 )
258 );
259
260 if (!m_message_diag.IsEmpty())
261 retmsg.Write(L"\n\n%s", m_message_diag.c_str());
262
263 return retmsg;
264 }
265
266
267 // ------------------------------------------------------------------------
268 wxString Exception::CancelEvent::FormatDiagnosticMessage() const
269 {
270 return L"Action canceled: " + m_message_diag;
271 }
272
273 wxString Exception::CancelEvent::FormatDisplayMessage() const
274 {
275 return L"Action canceled: " + m_message_diag;
276 }
277
278 // --------------------------------------------------------------------------------------
279 // Exception::BadStream (implementations)
280 // --------------------------------------------------------------------------------------
281 wxString Exception::BadStream::FormatDiagnosticMessage() const
282 {
283 FastFormatUnicode retval;
284 _formatDiagMsg(retval);
285 return retval;
286 }
287
288 wxString Exception::BadStream::FormatDisplayMessage() const
289 {
290 FastFormatUnicode retval;
291 _formatUserMsg(retval);
292 return retval;
293 }
294
295 void Exception::BadStream::_formatDiagMsg( FastFormatUnicode& dest ) const
296 {
297 dest.Write( L"Path: " );
298 if (!StreamName.IsEmpty())
299 dest.Write( L"%s", StreamName.c_str() );
300 else
301 dest.Write( L"[Unnamed or unknown]" );
302
303 if (!m_message_diag.IsEmpty())
304 dest.Write(L"\n%s", m_message_diag.c_str());
305 }
306
307 void Exception::BadStream::_formatUserMsg( FastFormatUnicode& dest ) const
308 {
309 dest.Write( _("Path: ") );
310 if (!StreamName.IsEmpty())
311 dest.Write( L"%s", StreamName.c_str() );
312 else
313 dest.Write( _("[Unnamed or unknown]") );
314
315 if (!m_message_user.IsEmpty())
316 dest.Write(L"\n%s", m_message_user.c_str());
317 }
318
319 // --------------------------------------------------------------------------------------
320 // Exception::CannotCreateStream (implementations)
321 // --------------------------------------------------------------------------------------
322 wxString Exception::CannotCreateStream::FormatDiagnosticMessage() const
323 {
324 FastFormatUnicode retval;
325 retval.Write("File could not be created.");
326 _formatDiagMsg(retval);
327 return retval;
328 }
329
330 wxString Exception::CannotCreateStream::FormatDisplayMessage() const
331 {
332 FastFormatUnicode retval;
333 retval.Write(_("A file could not be created."));
334 _formatUserMsg(retval);
335 return retval;
336 }
337
338 // --------------------------------------------------------------------------------------
339 // Exception::FileNotFound (implementations)
340 // --------------------------------------------------------------------------------------
341 wxString Exception::FileNotFound::FormatDiagnosticMessage() const
342 {
343 FastFormatUnicode retval;
344 retval.Write("File not found.");
345 _formatDiagMsg(retval);
346 return retval;
347 }
348
349 wxString Exception::FileNotFound::FormatDisplayMessage() const
350 {
351 FastFormatUnicode retval;
352 retval.Write(_("File not found."));
353 _formatUserMsg(retval);
354 return retval;
355 }
356
357 // --------------------------------------------------------------------------------------
358 // Exception::AccessDenied (implementations)
359 // --------------------------------------------------------------------------------------
360 wxString Exception::AccessDenied::FormatDiagnosticMessage() const
361 {
362 FastFormatUnicode retval;
363 retval.Write("Permission denied to file.");
364 _formatDiagMsg(retval);
365 return retval;
366 }
367
368 wxString Exception::AccessDenied::FormatDisplayMessage() const
369 {
370 FastFormatUnicode retval;
371 retval.Write(_("Permission denied while trying to open file, likely due to insufficient user account rights."));
372 _formatUserMsg(retval);
373 return retval;
374 }
375
376 // --------------------------------------------------------------------------------------
377 // Exception::EndOfStream (implementations)
378 // --------------------------------------------------------------------------------------
379 wxString Exception::EndOfStream::FormatDiagnosticMessage() const
380 {
381 FastFormatUnicode retval;
382 retval.Write("Unexpected end of file or stream.");
383 _formatDiagMsg(retval);
384 return retval;
385 }
386
387 wxString Exception::EndOfStream::FormatDisplayMessage() const
388 {
389 FastFormatUnicode retval;
390 retval.Write(_("Unexpected end of file or stream encountered. File is probably truncated or corrupted."));
391 _formatUserMsg(retval);
392 return retval;
393 }
394
395 // --------------------------------------------------------------------------------------
396 // Exceptions from Errno (POSIX)
397 // --------------------------------------------------------------------------------------
398
399 // Translates an Errno code into an exception.
400 // Throws an exception based on the given error code (usually taken from ANSI C's errno)
401 BaseException* Exception::FromErrno( const wxString& streamname, int errcode )
402 {
403 pxAssumeDev( errcode != 0, "Invalid NULL error code? (errno)" );
404
405 switch( errcode )
406 {
407 case EINVAL:
408 pxFailDev( L"Invalid argument" );
409 return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)" );
410
411 case EACCES: // Access denied!
412 return new Exception::AccessDenied( streamname );
413
414 case EMFILE: // Too many open files!
415 return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"Too many open files"); // File handle allocation failure
416
417 case EEXIST:
418 return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"File already exists");
419
420 case ENOENT: // File not found!
421 return new Exception::FileNotFound( streamname );
422
423 case EPIPE:
424 return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Broken pipe");
425
426 case EBADF:
427 return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Bad file number");
428
429 default:
430 return &(new Exception::BadStream( streamname ))->SetDiagMsg(pxsFmt( L"General file/stream error [errno: %d]", errcode ));
431 }
432 }

  ViewVC Help
Powered by ViewVC 1.1.22