Skip to content

Commit dee63f4

Browse files
committed
Provide stacktrace for unimplemented native CAPI
1 parent 8b52abd commit dee63f4

File tree

3 files changed

+55
-8
lines changed

3 files changed

+55
-8
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,45 @@ PyAPI_FUNC(int64_t *) GraalPy_get_finalize_capi_pointer_array() {
964964
return reset_func_ptrs;
965965
}
966966

967+
#if ((__linux__ && __GNU_LIBRARY__) || __APPLE__)
968+
969+
#include <stdlib.h>
970+
#include <string.h>
971+
#include <execinfo.h>
972+
973+
static void print_c_stacktrace() {
974+
size_t max_stack_size = 16;
975+
void* stack = calloc(sizeof(void*), max_stack_size);
976+
if (stack == NULL) {
977+
return;
978+
}
979+
980+
size_t stack_size = backtrace(stack, max_stack_size);
981+
char** symbols = backtrace_symbols(stack, stack_size);
982+
if (symbols == NULL) {
983+
free(stack);
984+
return;
985+
}
986+
987+
for (size_t i = 0; i < stack_size; i++) {
988+
printf ("%s\n", symbols[i]);
989+
}
990+
}
991+
992+
#else
993+
994+
static void print_c_stacktrace() {
995+
// other platforms are not supported
996+
}
997+
998+
#endif
999+
9671000
static void unimplemented(const char* name) {
968-
printf("Function not implemented in GraalPy: %s\n", name);
1001+
printf("Native stacktrace:\n");
1002+
print_c_stacktrace();
9691003
}
9701004

971-
#define FUNC_NOT_IMPLEMENTED unimplemented(__func__); exit(-1);
1005+
#define FUNC_NOT_IMPLEMENTED unimplemented(__func__); GraalPyTrufflePrintStacktrace(__func__, "Function not implemented in GraalPy: "); exit(-1);
9721006

9731007
// {{start CAPI_BUILTINS}}
9741008
#include "capi.gen.c.h"

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextContextBuiltins.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -46,6 +46,8 @@
4646
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Pointer;
4747
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObject;
4848
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer;
49+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.VoidNoReturn;
50+
import static com.oracle.graal.python.runtime.exception.ExceptionUtils.printPythonLikeStackTrace;
4951

5052
import com.oracle.graal.python.PythonLanguage;
5153
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -60,6 +62,7 @@
6062
import com.oracle.graal.python.nodes.call.CallNode;
6163
import com.oracle.graal.python.runtime.PythonContext;
6264
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
65+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6366
import com.oracle.truffle.api.dsl.Bind;
6467
import com.oracle.truffle.api.dsl.Cached;
6568
import com.oracle.truffle.api.dsl.Specialization;
@@ -68,6 +71,18 @@
6871

6972
public final class PythonCextContextBuiltins {
7073

74+
@CApiBuiltin(ret = VoidNoReturn, args = {ConstCharPtrAsTruffleString, ConstCharPtrAsTruffleString}, call = Ignored)
75+
abstract static class PyTrufflePrintStacktrace extends CApiBinaryBuiltinNode {
76+
77+
@Specialization
78+
@TruffleBoundary
79+
static Object stacktrace(TruffleString where, TruffleString msg) {
80+
System.err.println(msg.toJavaStringUncached() + where.toJavaStringUncached());
81+
printPythonLikeStackTrace();
82+
return 0;
83+
}
84+
}
85+
7186
@CApiBuiltin(ret = PyObjectTransfer, args = {ConstCharPtrAsTruffleString, PyObject}, call = Direct)
7287
abstract static class PyContextVar_New extends CApiBinaryBuiltinNode {
7388
@Specialization

mx.graalpython/mx_graalpython.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,8 @@ def get_jdk():
221221
return mx.get_jdk()
222222

223223

224-
def full_python(args, **kwargs):
224+
def full_python(args, env=None):
225225
"""Run python from standalone build (unless kwargs are given). Does not build GraalPython sources automatically."""
226-
if kwargs:
227-
return python(args, **kwargs)
228226

229227
if not any(arg.startswith('--python.WithJavaStacktrace') for arg in args):
230228
args.insert(0, '--python.WithJavaStacktrace=1')
@@ -258,7 +256,7 @@ def full_python(args, **kwargs):
258256
"To build it: mx python-jvm\n" +
259257
"Alternatively use: mx python --hosted")
260258

261-
mx.run([graalpy_path] + args)
259+
mx.run([graalpy_path] + args, env=env)
262260

263261

264262
def handle_debug_arg(args):
@@ -1084,7 +1082,7 @@ def graalpytest(args):
10841082
if args.python:
10851083
return mx.run([args.python] + cmd_args, nonZeroIsFatal=True, env=env)
10861084
else:
1087-
return do_run_python(cmd_args, env=env)
1085+
return full_python(cmd_args, env=env)
10881086

10891087

10901088
def _list_graalpython_unittests(paths=None, exclude=None):

0 commit comments

Comments
 (0)