From d9a1ab52e521a53924bdb858f59244345195688c Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 13 Sep 2022 10:24:56 -0700 Subject: [PATCH] moved more python init to main thread and public sources --- .efrocachemap | 91 ++--- .idea/dictionaries/ericf.xml | 3 + CHANGELOG.md | 6 +- .../ba_data/python/._bainternal_sources_hash | 2 +- assets/src/ba_data/python/ba/_bootstrap.py | 16 +- .../.idea/dictionaries/ericf.xml | 3 + .../inspectionProfiles/Project_Default.xml | 1 + src/ballistica/audio/audio_server.cc | 2 +- src/ballistica/ballistica.cc | 8 +- src/ballistica/internal/app_internal.h | 2 +- src/ballistica/logic/logic.cc | 20 +- .../python/methods/python_methods_app.cc | 1 + src/ballistica/python/python.cc | 352 ++++++++++-------- src/ballistica/python/python.h | 8 +- src/ballistica/python/python_ref.cc | 5 - src/meta/.meta_manifest_public.json | 3 +- src/meta/Makefile | 9 +- src/meta/bameta/python_embedded/bootstrap.py | 4 +- .../python_embedded/bootstrap_monolithic.py | 22 ++ 19 files changed, 318 insertions(+), 240 deletions(-) create mode 100644 src/meta/bameta/python_embedded/bootstrap_monolithic.py diff --git a/.efrocachemap b/.efrocachemap index ebd14c62..82e6f6f8 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3995,50 +3995,51 @@ "assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e", "assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34", "ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a", - "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/4c/c8/30631d3154a8c450b105da4fba36", - "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/81/c8/19c1a99a50a074027e85485b48ef", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5f/5f/93f8a60c6f6d58352a83540792ba", - "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b5/1c/c0fe6d5570d238872bfc839b46ac", - "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b6/92/91c7675daecf9f2c01672f45b420", - "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f5/49/7fff46b30c288ffc7e94c9fd4182", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e9/f3/99c96b36694274aab5f44f0a8c78", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/30/19/031ab0138f689d0fc7698c55f514", - "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/78/9b/6613bcdbd99cba2abd8994da47e9", - "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/85/83/8be76939bf30ad8d43d189099b4c", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a5/bc/374eaeb09819570ba9b9c30707e0", - "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/37/40/306b6050cc2ab7ce40b8a1935989", - "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/03/6b/3bdea294966f3d6b5f86ab3f15f1", - "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/e9/8f/86486943a8e2de808deb812cfdc6", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/33/72/b886fb6fdb0c36066da3a6d72f40", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bb/e5/425b5f16ffaae0ade584872e6b1c", - "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a3/c9/44b771f906edf3d63943acd535a8", - "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/17/b5/95fc75d8b8ee7dc24e2897309ff1", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/93/06/3ff8db73b443613e342010b8d26f", - "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/60/09/d6e216de302ff8dfbb5966b08f90", - "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/81/60/37044e17e52ca125c1d48af83d03", - "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fb/47/d505c3feea40888985dd335dc8c4", - "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4f/3d/20c78e744ac26a13b7418166d675", - "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/77/67a1fafff2c1918b1661b71ecaa0", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9b/00/f11d8f7f79c9b692b84f6dbd54dc", - "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f8/3a/0cd5030cbe13f99bf23d05ee6cfb", - "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5b/2a/3be2a55cbd63f9c42618c4013c87", - "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/09/ef/8fbfc6032e6a6089215c3dc365a1", - "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f8/79/31ecc50de3e52c55a1569b8b9438", - "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8a/a0/3ef54e3c6c3c777f8a221da16c14", - "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ee/a8/07c5e78d027bfc1acc88a25932b4", - "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/f5/a161f6c194a64f371e35e31bbfca", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/56/45/b6b9259f447f19ef0643b972bc64", - "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3b/79/592c41691e94807d23a783723861", - "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/13/d9/36f4cf8527494f419db74ae6c78f", - "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ee/e5/7f0677e6fb8d7cfa169930579712", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/69/c1/1694e8c7f55ac1c07277a2b5d7c2", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/73/5d/e1960323b7229bf34dd88a4b7a72", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/2c/13/30518d52dfa93a303ba6033f13d4", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/dc/41/911fb9a80bbe2e8234d8610b0cf3", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/be/e0/9c48a3fc8c3a0caf8a5c2c88ddf4", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/02/bd/6e08bef172191198f82e61f714f6", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/f2/3e/5fbbe38fa5047ac11b10f214ecd9", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/4f/cf/09c154037d8f597fcac94fcf5723", + "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/c4/9784ffa7a202da7e851c447dc69a", + "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f0/15/1ffcc9804e84eaa6a652be53cbbd", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ac/45/ff0681bcf7d1c5ac2c191d288434", + "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7f/27/4a4158050c3d77a7021e12bb9d20", + "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f1/c9/048c9c9267b456ff7e5610624fbd", + "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/fe/6afe3275a46a1384c348ee3917bc", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/de/e3/69d0a6f6cbfba5a6e0d74c0442ba", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/06/b6/824ee73b255e99093aeae719e2e4", + "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c7/0e/3dd207020a393e2fff196918e986", + "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/d3/3698352ea276344dd12e969da09e", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ff/b3/5e9acbef286f6738de3023011556", + "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ab/ab/50ea4865929b418bf25dac3f475d", + "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e2/9f/aae9e3204175fce33a75d486008a", + "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/98/89/63eec19c696e364e349b0d200e91", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5b/75/bc745b50536aade78db0150d9d9e", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/94/06/ba7c0d3e3d3e9d02594871687ec9", + "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a2/ea/87883b1f4063980a1a40a112f9ce", + "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/da/0b/16a433cafa1e2a7f87caf83409bf", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/3a/4c/8aa877e66c3a7ad25dbd0e075ef8", + "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/83/07/b36ff25c01d4790b4758e0c86e68", + "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4b/02/e1d6afd343ce32d53c134c5fc4e7", + "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ed/18/45e61446f5f7e02624fb87fb8c97", + "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cf/46/393131611fa1395fd9c173d8426f", + "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2d/2e/d4a8ba6f7c46da387394f4542d02", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/df/6c/cafe5794323f445392e63114f14b", + "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/00/ba/5c85c98957ac9f0832a01ea83168", + "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/0c/c85a8d0a8b43dac24a94417297fb", + "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f1/ca/c78a414c9d6ec0ffb647585c3e33", + "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/6a/83518a680d4917e3356d21d3650d", + "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6a/39/2e1794bf48cbc4c67c63b9527a68", + "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3b/64/48be465941f4f1aa3332a1d32f6a", + "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/63/03/d9a332d36a337086b639c4240674", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ea/ca/533d54af50f2b5750f7c407dcbd5", + "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/17/d6/e9af602218f3dd14a5bedb6c7eb2", + "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a6/cc/2ee87bb2ead38a3bf7d8b2588f39", + "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e5/ef/91bb1dfff04d62899cbe363b0d23", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/a2/7a/faf4c2744e2762e58d0119dafa72", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/7d/66/d3aafe52f5d44a23aa426bc8e602", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/63/5b/a3d3b19e7583a72cbdeefbd00f7e", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/60/14/3a28abc1b1b87b14f05d86a2e900", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/6c/a3/ded8df37d31c54c4ab66e224015a", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/2b/c6/a8701e03471178983957c33026ff", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/7e/16/307bb68c0561181ba701d0bcd350", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/09/b3/2fd1934cb6f0d2454e222c60ef3b", "src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/7d/3e/229a581cb2454ed856f1d8b564a7", - "src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/98/12/571b2160d69d42580e8f31fa6a8d" + "src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02", + "src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd" } \ No newline at end of file diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml index 06bafff1..6ae45394 100644 --- a/.idea/dictionaries/ericf.xml +++ b/.idea/dictionaries/ericf.xml @@ -234,6 +234,7 @@ benning bfiledir bfiles + bgdynamics bgmodel bgrn bgterrain @@ -415,6 +416,7 @@ cleanlist cleanupcheck cleanupchecks + clearsign clientid clientlist clienttobasn @@ -1648,6 +1650,7 @@ nettest nettesting netutils + networkwrite nevermind newactivity newdamage diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c0642d1..bf01925f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.7 (build 20837, api 7, 2022-09-12) +### 1.7.7 (build 20840, api 7, 2022-09-13) - Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread. - Improved logging of missing playlist game types. - Some ba.Lstr functionality can now be used in background threads. @@ -24,7 +24,9 @@ - Renamed C++ Media to Assets. - Removed 'scores to beat' list in coop which was only ever functional in limited cases on the Mac version. Perhaps that feature can reappear in a cross-platform way sometime. - Simplified C++ bootstrapping to allocate all globals in one place. -- Renamed C++ Game class to Logic. +- Renamed C++ Game classes to Logic. +- The app now bootstraps Python in the main thread instead of the logic thread. This will keep things more consistent later when we are able to run under an already-existing Python interpreter. +- Python and _ba are now completely initialized in public source code. Now we just need to enable the app to survive without _bainternal and it'll be possible to build a 100% open source app. ### 1.7.6 (build 20687, api 7, 2022-08-11) - Cleaned up da MetaSubsystem code. diff --git a/assets/src/ba_data/python/._bainternal_sources_hash b/assets/src/ba_data/python/._bainternal_sources_hash index 0321a786..6e9f924c 100644 --- a/assets/src/ba_data/python/._bainternal_sources_hash +++ b/assets/src/ba_data/python/._bainternal_sources_hash @@ -1 +1 @@ -304827393730630459319623179535089986346 \ No newline at end of file +222094078620857897443553282652634355523 \ No newline at end of file diff --git a/assets/src/ba_data/python/ba/_bootstrap.py b/assets/src/ba_data/python/ba/_bootstrap.py index f25876fd..8bbf492e 100644 --- a/assets/src/ba_data/python/ba/_bootstrap.py +++ b/assets/src/ba_data/python/ba/_bootstrap.py @@ -5,7 +5,6 @@ from __future__ import annotations import os import sys -import signal import threading from typing import TYPE_CHECKING @@ -38,7 +37,7 @@ def bootstrap() -> None: # Give a soft warning if we're being used with a different binary # version than we expect. - expected_build = 20837 + expected_build = 20840 running_build: int = env['build_number'] if running_build != expected_build: print( @@ -48,16 +47,11 @@ def bootstrap() -> None: f' This might cause the app to error or misbehave.', file=sys.stderr) - # Tell Python to not handle SIGINT itself (it normally generates - # KeyboardInterrupts which make a mess; we want to intercept them - # for simple clean exit). We capture interrupts per-platform in - # the C++ layer. - # Note: I tried creating a handler in Python but it seemed to often have - # a delay of up to a second before getting called. (not a huge deal - # but I'm picky). - signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling. + # In bootstrap_monolithic.py we told Python not to handle SIGINT itself + # (because that must be done in the main thread). Now we finish the + # job by adding our own handler to replace it. - # ..though it turns out we need to set up our C signal handling AFTER + # Note: I've found we need to set up our C signal handling AFTER # we've told Python to disable its own; otherwise (on Mac at least) it # wipes out our existing C handler. _ba.setup_sigint() diff --git a/ballisticacore-cmake/.idea/dictionaries/ericf.xml b/ballisticacore-cmake/.idea/dictionaries/ericf.xml index 597eda1d..16d6b197 100644 --- a/ballisticacore-cmake/.idea/dictionaries/ericf.xml +++ b/ballisticacore-cmake/.idea/dictionaries/ericf.xml @@ -119,6 +119,7 @@ bdea benning bezanson + bgdynamics bgra bigendian bilinear @@ -226,6 +227,7 @@ classdict classline cleanupcheck + clearsign clientid clientinfo clienttobasn @@ -849,6 +851,7 @@ netcode netplay nettest + networkwrite newactivity newchild newimg diff --git a/ballisticacore-cmake/.idea/inspectionProfiles/Project_Default.xml b/ballisticacore-cmake/.idea/inspectionProfiles/Project_Default.xml index ffa57a65..bccdbc35 100644 --- a/ballisticacore-cmake/.idea/inspectionProfiles/Project_Default.xml +++ b/ballisticacore-cmake/.idea/inspectionProfiles/Project_Default.xml @@ -58,6 +58,7 @@ + diff --git a/src/ballistica/audio/audio_server.cc b/src/ballistica/audio/audio_server.cc index 86d02fb8..a63451d7 100644 --- a/src/ballistica/audio/audio_server.cc +++ b/src/ballistica/audio/audio_server.cc @@ -86,7 +86,7 @@ class AudioServer::ThreadSource : public Object { auto play_id() const -> uint32_t { return (play_count_ << 16u) | (static_cast(id_) & 0xFFFFu); } - void UpdateAvailability(); + auto UpdateAvailability() -> void; auto GetDefaultOwnerThread() const -> ThreadTag override; auto client_source() const -> AudioSource* { return client_source_.get(); } auto source_sound() const -> SoundData* { diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc index fd3c28b4..5a4c81db 100644 --- a/src/ballistica/ballistica.cc +++ b/src/ballistica/ballistica.cc @@ -32,7 +32,7 @@ namespace ballistica { // These are set automatically via script; don't modify them here. -const int kAppBuildNumber = 20837; +const int kAppBuildNumber = 20840; const char* kAppVersion = "1.7.7"; // Our standalone globals. @@ -88,9 +88,10 @@ auto BallisticaMain(int argc, char** argv) -> int { g_platform = Platform::Create(); g_app = new App(argc, argv); + g_app_internal = CreateAppInternal(); g_main_thread = new Thread(ThreadTag::kMain, ThreadSource::kWrapMain); - g_python = new Python(); g_app_flavor = g_platform->CreateAppFlavor(); + g_python = Python::Create(); g_graphics = g_platform->CreateGraphics(); g_graphics_server = new GraphicsServer(); g_audio = new Audio(); @@ -107,7 +108,6 @@ auto BallisticaMain(int argc, char** argv) -> int { g_network_reader = new NetworkReader(); g_network_writer = new NetworkWriter(); g_input = new Input(); - g_app_internal = CreateAppInternal(); g_logic = new Logic(); g_scene_v1 = new SceneV1(); if (!HeadlessMode()) { @@ -220,7 +220,7 @@ auto FatalError(const std::string& message) -> void { FatalError::ReportFatalError(message, false); bool exit_cleanly = !IsUnmodifiedBlessedBuild(); bool handled = FatalError::HandleFatalError(exit_cleanly, false); - assert(handled); + BA_PRECONDITION(handled); } auto GetAppInstanceUUID() -> const std::string& { diff --git a/src/ballistica/internal/app_internal.h b/src/ballistica/internal/app_internal.h index 3c26ee9b..076c246f 100644 --- a/src/ballistica/internal/app_internal.h +++ b/src/ballistica/internal/app_internal.h @@ -16,7 +16,7 @@ class AppInternal { public: virtual ~AppInternal() {} - virtual auto PyInitialize(void* pyconfig) -> void = 0; + virtual auto DefineInternalModule() -> void = 0; virtual auto PythonPostInit() -> void = 0; virtual auto HasBlessingHash() -> bool = 0; virtual auto PutLog(bool fatal) -> bool = 0; diff --git a/src/ballistica/logic/logic.cc b/src/ballistica/logic/logic.cc index 90a31040..795951ac 100644 --- a/src/ballistica/logic/logic.cc +++ b/src/ballistica/logic/logic.cc @@ -83,10 +83,20 @@ auto Logic::OnAppStart() -> void { auto Logic::OnAppStartInThread() -> void { try { - // Our thread should hold the Python GIL any time it is running. - // TODO(ericf): It could be better to have each individual Python call - // we make acquire the GIL. Then we're not holding it during long - // bits of C++ logic. + // Our thread should not be holding the GIL here at the start (and + // probably not have any Python state at all). So here we set both + // of those up. + assert(!PyGILState_Check()); + PyGILState_Ensure(); + + // Tell our thread that it should grab the Python GIL any time it + // is running something and release it when done. + // TODO(ericf): It could be good to explore the idea of having + // individual runnables grab the GIL instead of doing it here at the + // thread level. Though its a bit freeing to know that we can run + // Python code at any time in the logic thread without worry. We can + // also consider explicitly releasing the GIL in the logic thread + // during long operations where we know no Python will occur. thread_->SetAcquiresPythonGIL(); // We want to be informed when our thread is pausing. @@ -98,7 +108,7 @@ auto Logic::OnAppStartInThread() -> void { // Init python and apply our settings immediately. // This way we can get started loading stuff in the background // and it'll come in with the correct texture quality etc. - g_python->Reset(true); + g_python->InitBallisticaPython(); } catch (const std::exception& e) { // If anything went wrong, trigger a deferred error. // This way it is more likely we can show a fatal error dialog diff --git a/src/ballistica/python/methods/python_methods_app.cc b/src/ballistica/python/methods/python_methods_app.cc index 54a10daf..d8a7fc6f 100644 --- a/src/ballistica/python/methods/python_methods_app.cc +++ b/src/ballistica/python/methods/python_methods_app.cc @@ -701,6 +701,7 @@ auto PyCommitConfig(PyObject* self, PyObject* args, PyObject* keywds) auto PyEnv(PyObject* self) -> PyObject* { BA_PYTHON_TRY; + assert(g_app->is_bootstrapped); static PyObject* env_obj = nullptr; diff --git a/src/ballistica/python/python.cc b/src/ballistica/python/python.cc index 169564bd..ae8d285f 100644 --- a/src/ballistica/python/python.cc +++ b/src/ballistica/python/python.cc @@ -853,6 +853,19 @@ auto Python::GetPyVector3f(PyObject* o) -> Vector3f { Python::Python() = default; +auto Python::Create() -> Python* { + assert(InMainThread()); + + Python* python = new Python(); + python->InitCorePython(); + + // After we bootstrap Python here in the main thread we release the GIL. + // We'll explicitly reacquire it anytime we need it (mainly in the logic + // thread once that comes up later). + PyEval_SaveThread(); + return python; +} + static struct PyModuleDef ba_module_def = {PyModuleDef_HEAD_INIT}; static auto ba_exec(PyObject* module) -> int { @@ -885,161 +898,183 @@ static auto PyInit__ba() -> PyObject* { return module; } -void Python::Reset(bool do_init) { +auto Python::InitCorePython() -> void { + assert(!inited_); + assert(InMainThread()); + // Flip on some extra runtime debugging options in debug builds. + // https://docs.python.org/3/library/devmode.html#devmode + int dev_mode{g_buildconfig.debug_build()}; + + // Pre-config as isolated if we include our own Python and as standard + // otherwise. + PyPreConfig preconfig; + if (g_platform->ContainsPythonDist()) { + PyPreConfig_InitIsolatedConfig(&preconfig); + } else { + PyPreConfig_InitPythonConfig(&preconfig); + } + preconfig.dev_mode = dev_mode; + + // We want consistent utf-8 everywhere (Python used to default to + // windows-specific file encodings, etc.) + preconfig.utf8_mode = 1; + + PyStatus status = Py_PreInitialize(&preconfig); + BA_PRECONDITION(!PyStatus_Exception(status)); + + // Configure as isolated if we include our own Python and as standard + // otherwise. + PyConfig config; + if (g_platform->ContainsPythonDist()) { + PyConfig_InitIsolatedConfig(&config); + } else { + PyConfig_InitPythonConfig(&config); + } + config.dev_mode = dev_mode; + if (!g_buildconfig.debug_build()) { + config.optimization_level = 1; + } + + // In cases where we bundle Python, set up all paths explicitly. + // https://docs.python.org/3/c-api/init_config.html#path-configuration + if (g_platform->ContainsPythonDist()) { + PyConfig_SetBytesString(&config, &config.base_exec_prefix, ""); + PyConfig_SetBytesString(&config, &config.base_executable, ""); + PyConfig_SetBytesString(&config, &config.base_prefix, ""); + PyConfig_SetBytesString(&config, &config.exec_prefix, ""); + PyConfig_SetBytesString(&config, &config.executable, ""); + PyConfig_SetBytesString(&config, &config.prefix, ""); + + // Interesting note: it seems we can pass relative paths here but + // they wind up in sys.path as absolute paths (unlike entries we add + // to sys.path after things are up and running). + if (g_buildconfig.ostype_windows()) { + // Windows Python looks for Lib and DLLs dirs by default, along with + // some others, but we want to be more explicit in limiting to these. It + // also seems that windows Python's paths can be incorrect if we're in + // strange dirs such as \\wsl$\Ubuntu-18.04\ that we get with WSL build + // setups. + + // NOTE: Python for windows actually comes with 'Lib', not 'lib', but + // it seems the interpreter defaults point to ./lib (as of 3.8.5). + // Normally this doesn't matter since windows is case-insensitive but + // under WSL it does. + // So we currently bundle the dir as 'lib' and use that in our path so + // that everything is happy (both with us and with python.exe). + PyWideStringList_Append(&config.module_search_paths, + Py_DecodeLocale("lib", nullptr)); + PyWideStringList_Append(&config.module_search_paths, + Py_DecodeLocale("DLLs", nullptr)); + } else { + PyWideStringList_Append(&config.module_search_paths, + Py_DecodeLocale("pylib", nullptr)); + } + config.module_search_paths_set = 1; + } + + // Let Python know how to spin up our _ba module. + PyImport_AppendInittab("_ba", &PyInit__ba); + + // Let Python know how to spin up the _bainternal module. + g_app_internal->DefineInternalModule(); + + // Init Python. + status = Py_InitializeFromConfig(&config); + BA_PRECONDITION(!PyStatus_Exception(status)); + + // Create a dict for execing just this bootstrap code in so + // we don't pollute the __main__ namespace. + auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)}; + + // Do a bit of basic bootstrapping here in the main thread. +#include "ballistica/generated/python_embedded/bootstrap_monolithic.inc" + PyObject* result = + PyRun_String(bootstrap_monolithic_code, Py_file_input, + bootstrap_context.get(), bootstrap_context.get()); + if (result == nullptr) { + PyErr_PrintEx(0); + + // Throw a simple exception so we don't get a stack trace. + throw std::logic_error( + "Error in ba Python bootstrapping. See log for details."); + } + Py_DECREF(result); + + // Grab __main__ in case we need to use it later. + // FIXME: put this in objs_ with everything else. + PyObject* m; + BA_PRECONDITION(m = PyImport_AddModule("__main__")); + BA_PRECONDITION(main_dict_ = PyModule_GetDict(m)); + + // Make sure we're running the Python version we require. + const char* ver = Py_GetVersion(); + if (strncmp(ver, "3.10", 4) != 0) { + FatalError("We require Python 3.10.x; instead found " + std::string(ver)); + } +} + +auto Python::InitBallisticaPython() -> void { + assert(InLogicThread()); + + // Create a dict for execing just this bootstrap code in so + // we don't pollute the __main__ namespace. + auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)}; + + // Get the app up and running. + // Run a few core bootstrappy things first: + // - get stdout/stderr redirection up so we can intercept python output + // - add our user and system script dirs to python path + // - create the ba.app instance. + +#include "ballistica/generated/python_embedded/bootstrap.inc" + PyObject* result = + PyRun_String(bootstrap_code, Py_file_input, bootstrap_context.get(), + bootstrap_context.get()); + if (result == nullptr) { + PyErr_PrintEx(0); + + // Throw a simple exception so we don't get a stack trace. + throw std::logic_error( + "Error in ba Python bootstrapping. See log for details."); + } + Py_DECREF(result); + + // Import and grab all the Python stuff we use from C++. +#include "ballistica/generated/python_embedded/binding.inc" + + g_app_internal->PythonPostInit(); + + // Alright I guess let's pull ba in to main, since pretty + // much all interactive commands will be using it. + // If we ever build the game as a pure python module we should + // of course not do this. + BA_PRECONDITION(PyRun_SimpleString("import ba") == 0); + + // Read the config file and store the config dict for easy access. + obj(ObjID::kReadConfigCall).Call(); + StoreObj(ObjID::kConfig, obj(ObjID::kApp).GetAttr("config").get()); + assert(PyDict_Check(obj(ObjID::kConfig).get())); + + // Turn off fancy-pants cyclic garbage-collection. + // We run it only at explicit times to avoid random hitches and keep + // things more deterministic. + // Non-reference-looped objects will still get cleaned up + // immediately, so we should try to structure things to avoid + // reference loops (just like Swift, ObjC, etc). + // FIXME - move this to Python code. + g_python->obj(Python::ObjID::kGCDisableCall).Call(); + inited_ = true; +} + +auto Python::Reset() -> void { assert(InLogicThread()); assert(g_python); assert(g_platform); + assert(inited_); - bool was_inited = inited_; - - if (inited_) { - ReleaseGamePadInput(); - ReleaseKeyboardInput(); - g_graphics->ReleaseFadeEndCommand(); - inited_ = false; - } - - if (!was_inited && do_init) { - // Flip on some extra runtime debugging options in debug builds. - // https://docs.python.org/3.10/library/devmode.html#devmode - int dev_mode{g_buildconfig.debug_build()}; - - // Pre-config as isolated if we include our own Python and as standard - // otherwise. - PyPreConfig preconfig; - if (g_platform->ContainsPythonDist()) { - PyPreConfig_InitIsolatedConfig(&preconfig); - } else { - PyPreConfig_InitPythonConfig(&preconfig); - } - preconfig.dev_mode = dev_mode; - - // We want consistent utf-8 everywhere (Python used to default to - // windows-specific file encodings, etc.) - preconfig.utf8_mode = 1; - - PyStatus status = Py_PreInitialize(&preconfig); - BA_PRECONDITION(!PyStatus_Exception(status)); - - // Configure as isolated if we include our own Python and as standard - // otherwise. - PyConfig config; - if (g_platform->ContainsPythonDist()) { - PyConfig_InitIsolatedConfig(&config); - } else { - PyConfig_InitPythonConfig(&config); - } - config.dev_mode = dev_mode; - if (!g_buildconfig.debug_build()) { - config.optimization_level = 1; - } - - // In cases where we bundle Python, set up all paths explicitly. - // see https://docs.python.org/3.8/ - // c-api/init_config.html#path-configuration - if (g_platform->ContainsPythonDist()) { - PyConfig_SetBytesString(&config, &config.base_exec_prefix, ""); - PyConfig_SetBytesString(&config, &config.base_executable, ""); - PyConfig_SetBytesString(&config, &config.base_prefix, ""); - PyConfig_SetBytesString(&config, &config.exec_prefix, ""); - PyConfig_SetBytesString(&config, &config.executable, ""); - PyConfig_SetBytesString(&config, &config.prefix, ""); - - // Interesting note: it seems we can pass relative paths here but - // they wind up in sys.path as absolute paths (unlike entries we add - // to sys.path after things are up and running). - if (g_buildconfig.ostype_windows()) { - // Windows Python looks for Lib and DLLs dirs by default, along with - // some others, but we want to be more explicit in limiting to these. It - // also seems that windows Python's paths can be incorrect if we're in - // strange dirs such as \\wsl$\Ubuntu-18.04\ that we get with WSL build - // setups. - - // NOTE: Python for windows actually comes with 'Lib', not 'lib', but - // it seems the interpreter defaults point to ./lib (as of 3.8.5). - // Normally this doesn't matter since windows is case-insensitive but - // under WSL it does. - // So we currently bundle the dir as 'lib' and use that in our path so - // that everything is happy (both with us and with python.exe). - PyWideStringList_Append(&config.module_search_paths, - Py_DecodeLocale("lib", nullptr)); - PyWideStringList_Append(&config.module_search_paths, - Py_DecodeLocale("DLLs", nullptr)); - } else { - PyWideStringList_Append(&config.module_search_paths, - Py_DecodeLocale("pylib", nullptr)); - } - config.module_search_paths_set = 1; - } - - // Let Python know how to spin up our _ba module. - PyImport_AppendInittab("_ba", &PyInit__ba); - - // Inits our _ba module and runs Py_Initialize(). - g_app_internal->PyInitialize(&config); - - // Grab __main__ in case we need to use it later. - PyObject* m; - BA_PRECONDITION(m = PyImport_AddModule("__main__")); - BA_PRECONDITION(main_dict_ = PyModule_GetDict(m)); - - // Make sure we're running the Python version we require. - const char* ver = Py_GetVersion(); - if (strncmp(ver, "3.10", 4) != 0) { - throw Exception("We require Python 3.10.x; instead found " - + std::string(ver)); - } - - // Create a dict for execing our bootstrap code in so - // we don't pollute the __main__ namespace. - auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)}; - - // Get the app up and running. - // Run a few core bootstrappy things first: - // - get stdout/stderr redirection up so we can intercept python output - // - add our user and system script dirs to python path - // - create the ba.app instance. - -#include "ballistica/generated/python_embedded/bootstrap.inc" - PyObject* result = - PyRun_String(bootstrap_code, Py_file_input, bootstrap_context.get(), - bootstrap_context.get()); - if (result == nullptr) { - PyErr_PrintEx(0); - - // Throw a simple exception so we don't get a stack trace. - throw std::logic_error( - "Error in ba Python bootstrapping. See log for details."); - } - Py_DECREF(result); - - // Import and grab all the Python stuff we use from C++. -#include "ballistica/generated/python_embedded/binding.inc" - - g_app_internal->PythonPostInit(); - - // Alright I guess let's pull ba in to main, since pretty - // much all interactive commands will be using it. - // If we ever build the game as a pure python module we should - // of course not do this. - BA_PRECONDITION(PyRun_SimpleString("import ba") == 0); - - // Read the config file and store the config dict for easy access. - obj(ObjID::kReadConfigCall).Call(); - StoreObj(ObjID::kConfig, obj(ObjID::kApp).GetAttr("config").get()); - assert(PyDict_Check(obj(ObjID::kConfig).get())); - - // Turn off fancy-pants cyclic garbage-collection. - // We run it only at explicit times to avoid random hitches and keep - // things more deterministic. - // Non-reference-looped objects will still get cleaned up - // immediately, so we should try to structure things to avoid - // reference loops (just like Swift, ObjC, etc). - g_python->obj(Python::ObjID::kGCDisableCall).Call(); - } - if (do_init) { - inited_ = true; - } + ReleaseGamePadInput(); + ReleaseKeyboardInput(); + g_graphics->ReleaseFadeEndCommand(); } auto Python::GetModuleMethods() -> std::vector { @@ -1114,8 +1149,6 @@ void Python::PushObjCall(ObjID obj_id, const std::string& arg) { }); } -Python::~Python() { Reset(false); } - auto Python::GetResource(const char* key, const char* fallback_resource, const char* fallback_value) -> std::string { assert(HaveGIL()); @@ -2259,12 +2292,13 @@ void Python::LogContextAuto() { } void Python::AcquireGIL() { + assert(InLogicThread()); auto debug_timing{g_app->debug_timing}; millisecs_t startms{debug_timing ? Platform::GetCurrentMilliseconds() : 0}; - if (thread_state_) { - PyEval_RestoreThread(thread_state_); - thread_state_ = nullptr; + if (logic_thread_state_) { + PyEval_RestoreThread(logic_thread_state_); + logic_thread_state_ = nullptr; } if (debug_timing) { @@ -2275,9 +2309,11 @@ void Python::AcquireGIL() { } } } + void Python::ReleaseGIL() { - assert(thread_state_ == nullptr); - thread_state_ = PyEval_SaveThread(); + assert(InLogicThread()); + assert(logic_thread_state_ == nullptr); + logic_thread_state_ = PyEval_SaveThread(); } void Python::AddCleanFrameCommand(const Object::Ref& c) { diff --git a/src/ballistica/python/python.h b/src/ballistica/python/python.h index e1094129..bf451032 100644 --- a/src/ballistica/python/python.h +++ b/src/ballistica/python/python.h @@ -80,9 +80,11 @@ class Python { static auto LogContextAuto() -> void; static auto LogContextNonLogicThread() -> void; Python(); - ~Python(); + static auto Create() -> Python*; - auto Reset(bool init = true) -> void; + auto InitCorePython() -> void; + auto InitBallisticaPython() -> void; + auto Reset() -> void; /// Add classes to the newly created ba module. static auto InitModuleClasses(PyObject* module) -> void; @@ -424,7 +426,7 @@ class Python { PyObject* empty_dict_object_{}; PyObject* main_dict_{}; PyObject* env_{}; - PyThreadState* thread_state_{}; + PyThreadState* logic_thread_state_{}; }; } // namespace ballistica diff --git a/src/ballistica/python/python_ref.cc b/src/ballistica/python/python_ref.cc index a91b6ada..008213d9 100644 --- a/src/ballistica/python/python_ref.cc +++ b/src/ballistica/python/python_ref.cc @@ -13,7 +13,6 @@ namespace ballistica { #pragma ide diagnostic ignored "RedundantCast" PythonRef::PythonRef(PyObject* obj_in, ReferenceBehavior b) { - assert(g_python); assert(Python::HaveGIL()); switch (b) { case kSteal: @@ -54,7 +53,6 @@ void PythonRef::Acquire(PyObject* obj_in) { void PythonRef::Steal(PyObject* obj_in) { BA_PRECONDITION(obj_in); - assert(g_python); assert(Python::HaveGIL()); // Assign before decrementing the old @@ -67,7 +65,6 @@ void PythonRef::Steal(PyObject* obj_in) { } void PythonRef::Release() { - assert(g_python); assert(Python::HaveGIL()); // Py_CLEAR uses a temp variable and assigns o to nullptr first @@ -113,7 +110,6 @@ auto PythonRef::ValueAsInt() const -> int64_t { } auto PythonRef::GetAttr(const char* name) const -> PythonRef { - assert(g_python); assert(Python::HaveGIL()); BA_PRECONDITION(obj_); PyObject* val = PyObject_GetAttrString(get(), name); @@ -149,7 +145,6 @@ auto PythonRef::UnicodeCheck() const -> bool { auto PythonRef::Call(PyObject* args, PyObject* keywds, bool print_errors) const -> PythonRef { assert(obj_); - assert(g_python); assert(Python::HaveGIL()); assert(CallableCheck()); assert(args); diff --git a/src/meta/.meta_manifest_public.json b/src/meta/.meta_manifest_public.json index dd1d3882..a5a5e757 100644 --- a/src/meta/.meta_manifest_public.json +++ b/src/meta/.meta_manifest_public.json @@ -2,5 +2,6 @@ "assets/src/ba_data/python/ba/_generated/__init__.py", "assets/src/ba_data/python/ba/_generated/enums.py", "src/ballistica/generated/python_embedded/binding.inc", - "src/ballistica/generated/python_embedded/bootstrap.inc" + "src/ballistica/generated/python_embedded/bootstrap.inc", + "src/ballistica/generated/python_embedded/bootstrap_monolithic.inc" ] \ No newline at end of file diff --git a/src/meta/Makefile b/src/meta/Makefile index 073a4d54..ce68dfee 100644 --- a/src/meta/Makefile +++ b/src/meta/Makefile @@ -17,7 +17,8 @@ sources: \ ../../assets/src/ba_data/python/ba/_generated/__init__.py \ ../../assets/src/ba_data/python/ba/_generated/enums.py \ ../ballistica/generated/python_embedded/binding.inc \ - ../ballistica/generated/python_embedded/bootstrap.inc + ../ballistica/generated/python_embedded/bootstrap.inc \ + ../ballistica/generated/python_embedded/bootstrap_monolithic.inc ../ballistica/generated/python_embedded/binding.inc : bameta/python_embedded/binding.py @$(PCOMMAND) gen_binding_code $< $@ @@ -25,6 +26,9 @@ sources: \ ../ballistica/generated/python_embedded/bootstrap.inc : bameta/python_embedded/bootstrap.py @$(PCOMMAND) gen_flat_data_code $< $@ bootstrap_code +../ballistica/generated/python_embedded/bootstrap_monolithic.inc : bameta/python_embedded/bootstrap_monolithic.py + @$(PCOMMAND) gen_flat_data_code $< $@ bootstrap_monolithic_code + ../../assets/src/ba_data/python/ba/_generated/__init__.py : ../../tools/batools/pcommand.py @$(PCOMMAND) gen_python_init_module $@ @@ -45,7 +49,8 @@ efrocache-list: @echo "../../assets/src/ba_data/python/ba/_generated/__init__.py" \ "../../assets/src/ba_data/python/ba/_generated/enums.py" \ "../ballistica/generated/python_embedded/binding.inc" \ - "../ballistica/generated/python_embedded/bootstrap.inc" + "../ballistica/generated/python_embedded/bootstrap.inc" \ + "../ballistica/generated/python_embedded/bootstrap_monolithic.inc" efrocache-build: sources diff --git a/src/meta/bameta/python_embedded/bootstrap.py b/src/meta/bameta/python_embedded/bootstrap.py index d84cd45d..85d06b15 100644 --- a/src/meta/bameta/python_embedded/bootstrap.py +++ b/src/meta/bameta/python_embedded/bootstrap.py @@ -1,6 +1,8 @@ # Released under the MIT License. See LICENSE for details. # -"""Initial ballistica bootstrapping.""" +"""Ballistica bootstrapping.""" + +# This code runs in the logic thread to bootstrap ballistica. from __future__ import annotations diff --git a/src/meta/bameta/python_embedded/bootstrap_monolithic.py b/src/meta/bameta/python_embedded/bootstrap_monolithic.py new file mode 100644 index 00000000..d6534a1a --- /dev/null +++ b/src/meta/bameta/python_embedded/bootstrap_monolithic.py @@ -0,0 +1,22 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Main thread bootstrapping for Python monolithic builds.""" + +# This code runs in the main thread just after the interpreter comes up. +# It should *ONLY* do things that must be done in the main thread and +# should not import any ballistica stuff. + +from __future__ import annotations + +import signal +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + pass + +# Tell Python to not handle SIGINT itself (it normally generates +# KeyboardInterrupts which make a mess; we want to intercept them +# for simple clean exit). We have to do this part here because it must +# run in the main thread. We add our own handler later in the logic thread +# alongside our other ba bootstrapping. +signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.