Last night I was running our usual Greybeard AMA on FreeBSD’s Discord server, when someone asked “I’ve been using Linux for years, but I also like FreeBSD. what can I do for FreeBSD, and what can FreeBSD do for me, as a Python Full Stack Developer?”
I started talking about FreeBSD Jails, ZFS, Boot Environments and more, but I also wanted to focus on DTrace. The ability to dynamically trace on production still sounds like magic to me. I know it isn’t, I’ve read the code and the papers, but the fact that I can ask the operating system questions on the fly, without recompiling, is amazing.
So when I was demoing DTrace, I also wanted to show the DTrace integrations with Python. Little did I know that the Python package on FreeBSD was not compiled with the --with-dtrace
option.
As a sane person, I setup a Jail (using Jailer, of course), cloned the FreeBSD ports tree and added the --with-dtrace
option back. It did not compile.
The first issue that we encountered was the following:
--- Include/pydtrace_probes.h --- dtrace: option requires an argument -- s
ah yes, looking over the Makefile we see the following
Include/pydtrace_probes.h: $(srcdir)/Include/pydtrace.d $(MKDIR_P) Include $(DTRACE) $(DFLAGS) -o $@ -h -s $< : sed in-place edit with POSIX-only tools sed 's/PYTHON_/PyDTrace_/' $@ > $@.tmp mv $@.tmp $@
(you can also view the source here)
As far as I can tell, the $<
thingie does not work with BSD Make, so how about if we try using gmake
instead?
I did the following changes to the Makefile
in the FreeBSD Ports tree. Basically adding gmake
into USES=
.
USES= compiler:c11 cpe ncurses pathfix pkgconfig \ - python:${PYTHON_DISTVERSION:R},env readline shebangfix ssl tar:xz + python:${PYTHON_DISTVERSION:R},env readline shebangfix ssl tar:xz gmake
Now let’s try compiling again.
We get the following errors now:
ld: error: undefined symbol: __dtraceenabled_python___function__entry
Ah yes, linking issues.
After an hour of digging we learned that the DTRACE_OBJS=
variable is set to… nothing. But it needs to be set to Python/pydtrace.o
. I was not able to fix this issue properly (in configure
, configure.ac
, or whatever madness that GNU Autotools use), so I just changed the line manually in the Makefile
.
Now let’s try compiling again.
We get the following error:
./Python/sysmodule.c:223:24: warning: passing 'const char *' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
Someone in the Discord chat recommended that I disable the LTO (Link-Time Optimization) option.
I did make clean
, I patched that line again, and here we go, one more time.
It’s compiling, it’s compiling, it’s compiling… aaaaand we’re done! Let’s do make install
===> Installing for python311-3.11.11 ===> Checking if python311 is already installed ===> Registering installation for python311-3.11.11 [python.srv0.hackerspace.am] Installing python311-3.11.11...
good! now let’s try DTrace with Python!
In one terminal, I ran Python, and in another one I got the following
# dtrace -l -n 'python*:::' ID PROVIDER MODULE FUNCTION NAME 85302 python8737 libpython3.11.so.1.0 sys_audit audit 85303 python8737 libpython3.11.so.1.0 sys_audit_tstate audit 85304 python8737 libpython3.11.so.1.0 _PyEval_EvalFrameDefault function-entry 85305 python8737 libpython3.11.so.1.0 dtrace_function_return function-return 85306 python8737 libpython3.11.so.1.0 _PyEval_EvalFrameDefault function-return 85307 python8737 libpython3.11.so.1.0 gc_collect_main gc-done 85308 python8737 libpython3.11.so.1.0 gc_collect_main gc-start 85309 python8737 libpython3.11.so.1.0 PyImport_ImportModuleLevelObject import-find-load-done 85310 python8737 libpython3.11.so.1.0 PyImport_ImportModuleLevelObject import-find-load-start 85311 python8737 libpython3.11.so.1.0 _PyEval_EvalFrameDefault line
Woohoo! Now I’m happy!
Okay, so what did we learn?
- There’s a little bit of GNUMake-ism in Python’s Makefile. Either we have to use
gmake
in FreeBSD when building Python or we need to submit an alternative to the upstream - Die GNU Autotools… I mean… the GNU Autotools usage in Python has an issue, where the generated Makefile does not set the
DTRACE_OBJS
correctly. Can anyone help with this? As a Pascal guy, reading GNU configure files makes me wanna die. - LTO is problematic. Solutions?
The real question is, how can we enable DTrace by default in FreeBSD packages for Python. DTrace is one of our market advantages and we should find a way to enable it everywhere we can.
This was a fun Greybeard AMA, where we touched multiple parts of the system. Looking forward for next week!
That’s all folks…