cosmopolitan/third_party/python/Python/fatality.c
Jōshin e16a7d8f3b
flip et / noet in modelines
`et` means `expandtab`.

```sh
rg 'vi: .* :vi' -l -0 | \
  xargs -0 sed -i '' 's/vi: \(.*\) et\(.*\)  :vi/vi: \1 xoet\2:vi/'
rg 'vi: .*  :vi' -l -0 | \
  xargs -0 sed -i '' 's/vi: \(.*\)noet\(.*\):vi/vi: \1et\2  :vi/'
rg 'vi: .*  :vi' -l -0 | \
  xargs -0 sed -i '' 's/vi: \(.*\)xoet\(.*\):vi/vi: \1noet\2:vi/'
```
2023-12-07 22:17:11 -05:00

163 lines
5.1 KiB
C

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
│ vi: set et ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Python 3 │
│ https://docs.python.org/3/license.html │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/weaken.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pylifecycle.h"
#include "third_party/python/Include/pythonrun.h"
#include "third_party/python/Include/sysmodule.h"
#include "third_party/python/Include/traceback.h"
_Py_IDENTIFIER(flush);
_Py_IDENTIFIER(stderr);
/* Import the site module (not into __main__ though) */
static void
_Py_FatalError_DumpTracebacks(int fd)
{
fputc('\n', stderr);
fflush(stderr);
/* display the current Python stack */
_Py_DumpTracebackThreads(fd, NULL, NULL);
}
/* Print the current exception (if an exception is set) with its traceback,
or display the current Python stack.
Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
called on catastrophic cases.
Return 1 if the traceback was displayed, 0 otherwise. */
static int
_Py_FatalError_PrintExc(int fd)
{
PyObject *ferr, *res;
PyObject *exception, *v, *tb;
int has_tb;
PyErr_Fetch(&exception, &v, &tb);
if (exception == NULL) {
/* No current exception */
return 0;
}
ferr = _PySys_GetObjectId(&PyId_stderr);
if (ferr == NULL || ferr == Py_None) {
/* sys.stderr is not set yet or set to None,
no need to try to display the exception */
return 0;
}
PyErr_NormalizeException(&exception, &v, &tb);
if (tb == NULL) {
tb = Py_None;
Py_INCREF(tb);
}
PyException_SetTraceback(v, tb);
if (exception == NULL) {
/* PyErr_NormalizeException() failed */
return 0;
}
has_tb = (tb != Py_None);
PyErr_Display(exception, v, tb);
Py_XDECREF(exception);
Py_XDECREF(v);
Py_XDECREF(tb);
/* sys.stderr may be buffered: call sys.stderr.flush() */
res = _PyObject_CallMethodId(ferr, &PyId_flush, NULL);
if (res == NULL)
PyErr_Clear();
else
Py_DECREF(res);
return has_tb;
}
/* Print fatal error message and abort */
void
Py_FatalError(const char *msg)
{
const int fd = fileno(stderr);
static int reentrant = 0;
#ifdef MS_WINDOWS
size_t len;
WCHAR* buffer;
size_t i;
#endif
if (reentrant) {
/* Py_FatalError() caused a second fatal error.
Example: _Py_FlushStdFiles() raises a recursion error. */
goto exit;
}
reentrant = 1;
fprintf(stderr, "Fatal Python error: %s\n", msg);
fflush(stderr); /* it helps in Windows debug build */
/* Check if the current thread has a Python thread state
and holds the GIL */
PyThreadState *tss_tstate = NULL; // PyGILState_GetThisThreadState();
if (tss_tstate != NULL) {
PyThreadState *tstate = PyThreadState_GET();
if (tss_tstate != tstate) {
/* The Python thread does not hold the GIL */
tss_tstate = NULL;
}
}
else {
/* Py_FatalError() has been called from a C thread
which has no Python thread state. */
}
int has_tstate_and_gil = (tss_tstate != NULL);
/* If an exception is set, print the exception with its traceback */
if (!_Py_FatalError_PrintExc(fd)) {
/* No exception is set, or an exception is set without traceback */
_Py_FatalError_DumpTracebacks(fd);
}
/* The main purpose of faulthandler is to display the traceback. We already
* did our best to display it. So faulthandler can now be disabled.
* (Don't trigger it on abort().) */
_PyFaulthandler_Fini();
/* Check if the current Python thread hold the GIL */
if (has_tstate_and_gil) {
/* Flush sys.stdout and sys.stderr */
_Py_FlushStdFiles();
}
#ifdef MS_WINDOWS
len = strlen(msg);
/* Convert the message to wchar_t. This uses a simple one-to-one
conversion, assuming that the this error message actually uses ASCII
only. If this ceases to be true, we will have to convert. */
buffer = alloca( (len+1) * (sizeof *buffer));
for( i=0; i<=len; ++i)
buffer[i] = msg[i];
OutputDebugStringW(L"Fatal Python error: ");
OutputDebugStringW(buffer);
OutputDebugStringW(L"\n");
#endif /* MS_WINDOWS */
exit:
#if defined(MS_WINDOWS) && defined(_DEBUG)
DebugBreak();
#endif
if (_weaken(__die)) _weaken(__die)();
abort();
}