gh-116622: Redirect stdout and stderr to system log when embedded in an Android app (#118063)

This commit is contained in:
Malcolm Smith 2024-04-30 15:00:31 +01:00 committed by GitHub
parent 11f8348d78
commit 3b268f4edc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 511 additions and 0 deletions

View file

@ -71,6 +71,9 @@ static PyStatus add_main_module(PyInterpreterState *interp);
static PyStatus init_import_site(void);
static PyStatus init_set_builtins_open(void);
static PyStatus init_sys_streams(PyThreadState *tstate);
#ifdef __ANDROID__
static PyStatus init_android_streams(PyThreadState *tstate);
#endif
static void wait_for_thread_shutdown(PyThreadState *tstate);
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
@ -1223,6 +1226,13 @@ init_interp_main(PyThreadState *tstate)
return status;
}
#ifdef __ANDROID__
status = init_android_streams(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
#endif
#ifdef Py_DEBUG
run_presite(tstate);
#endif
@ -2719,6 +2729,73 @@ done:
}
#ifdef __ANDROID__
#include <android/log.h>
static PyObject *
android_log_write_impl(PyObject *self, PyObject *args)
{
int prio = 0;
const char *tag = NULL;
const char *text = NULL;
if (!PyArg_ParseTuple(args, "isy", &prio, &tag, &text)) {
return NULL;
}
// Despite its name, this function is part of the public API
// (https://developer.android.com/ndk/reference/group/logging).
__android_log_write(prio, tag, text);
Py_RETURN_NONE;
}
static PyMethodDef android_log_write_method = {
"android_log_write", android_log_write_impl, METH_VARARGS
};
static PyStatus
init_android_streams(PyThreadState *tstate)
{
PyStatus status = _PyStatus_OK();
PyObject *_android_support = NULL;
PyObject *android_log_write = NULL;
PyObject *result = NULL;
_android_support = PyImport_ImportModule("_android_support");
if (_android_support == NULL) {
goto error;
}
android_log_write = PyCFunction_New(&android_log_write_method, NULL);
if (android_log_write == NULL) {
goto error;
}
// These log priorities match those used by Java's System.out and System.err.
result = PyObject_CallMethod(
_android_support, "init_streams", "Oii",
android_log_write, ANDROID_LOG_INFO, ANDROID_LOG_WARN);
if (result == NULL) {
goto error;
}
goto done;
error:
_PyErr_Print(tstate);
status = _PyStatus_ERR("failed to initialize Android streams");
done:
Py_XDECREF(result);
Py_XDECREF(android_log_write);
Py_XDECREF(_android_support);
return status;
}
#endif // __ANDROID__
static void
_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,
PyThreadState *tstate)