chore(internal): make PeriodicThread.awake() non-blocking on stopped threads#17707
chore(internal): make PeriodicThread.awake() non-blocking on stopped threads#17707
Conversation
Codeowners resolved as |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4586038113
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Performance SLOsComparing candidate r1viollet/fix-periodic-thread-awake-after-stop (dd5488f) with baseline main (56e77c7) 📈 Performance Regressions (2 suites)📈 iastaspects - 118/118✅ add_aspectTime: ✅ 103.685µs (SLO: <130.000µs 📉 -20.2%) vs baseline: +4.0% Memory: ✅ 43.922MB (SLO: <46.000MB -4.5%) vs baseline: +4.8% ✅ add_inplace_aspectTime: ✅ 101.341µs (SLO: <130.000µs 📉 -22.0%) vs baseline: +0.5% Memory: ✅ 44.344MB (SLO: <46.000MB -3.6%) vs baseline: +5.7% ✅ add_inplace_noaspectTime: ✅ 28.400µs (SLO: <40.000µs 📉 -29.0%) vs baseline: +0.8% Memory: ✅ 44.290MB (SLO: <46.000MB -3.7%) vs baseline: +5.6% ✅ add_noaspectTime: ✅ 48.740µs (SLO: <70.000µs 📉 -30.4%) vs baseline: +0.4% Memory: ✅ 44.049MB (SLO: <46.000MB -4.2%) vs baseline: +5.3% ✅ bytearray_aspectTime: ✅ 269.328µs (SLO: <400.000µs 📉 -32.7%) vs baseline: +0.5% Memory: ✅ 43.852MB (SLO: <46.000MB -4.7%) vs baseline: +5.0% ✅ bytearray_extend_aspectTime: ✅ 659.222µs (SLO: <800.000µs 📉 -17.6%) vs baseline: +0.9% Memory: ✅ 44.374MB (SLO: <46.000MB -3.5%) vs baseline: +6.2% ✅ bytearray_extend_noaspectTime: ✅ 271.325µs (SLO: <400.000µs 📉 -32.2%) vs baseline: +1.0% Memory: ✅ 43.944MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ bytearray_noaspectTime: ✅ 145.957µs (SLO: <300.000µs 📉 -51.3%) vs baseline: +0.3% Memory: ✅ 44.284MB (SLO: <46.000MB -3.7%) vs baseline: +5.7% ✅ bytes_aspectTime: ✅ 228.214µs (SLO: <300.000µs 📉 -23.9%) vs baseline: ~same Memory: ✅ 43.958MB (SLO: <46.000MB -4.4%) vs baseline: +4.9% ✅ bytes_noaspectTime: ✅ 137.807µs (SLO: <200.000µs 📉 -31.1%) vs baseline: -1.3% Memory: ✅ 43.968MB (SLO: <46.000MB -4.4%) vs baseline: +5.2% ✅ bytesio_aspectTime: ✅ 3.825ms (SLO: <5.000ms 📉 -23.5%) vs baseline: -0.1% Memory: ✅ 43.938MB (SLO: <46.000MB -4.5%) vs baseline: +4.8% ✅ bytesio_noaspectTime: ✅ 319.559µs (SLO: <420.000µs 📉 -23.9%) vs baseline: -0.2% Memory: ✅ 44.013MB (SLO: <46.000MB -4.3%) vs baseline: +5.3% ✅ capitalize_aspectTime: ✅ 89.278µs (SLO: <300.000µs 📉 -70.2%) vs baseline: -0.3% Memory: ✅ 43.918MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ capitalize_noaspectTime: ✅ 275.115µs (SLO: <300.000µs -8.3%) vs baseline: 📈 +10.2% Memory: ✅ 44.245MB (SLO: <46.000MB -3.8%) vs baseline: +5.9% ✅ casefold_aspectTime: ✅ 88.909µs (SLO: <500.000µs 📉 -82.2%) vs baseline: ~same Memory: ✅ 43.911MB (SLO: <46.000MB -4.5%) vs baseline: +4.7% ✅ casefold_noaspectTime: ✅ 309.842µs (SLO: <500.000µs 📉 -38.0%) vs baseline: +1.6% Memory: ✅ 43.910MB (SLO: <46.000MB -4.5%) vs baseline: +4.9% ✅ decode_aspectTime: ✅ 86.642µs (SLO: <100.000µs 📉 -13.4%) vs baseline: -0.5% Memory: ✅ 43.957MB (SLO: <46.000MB -4.4%) vs baseline: +5.1% ✅ decode_noaspectTime: ✅ 157.745µs (SLO: <210.000µs 📉 -24.9%) vs baseline: +1.5% Memory: ✅ 43.818MB (SLO: <46.000MB -4.7%) vs baseline: +4.6% ✅ encode_aspectTime: ✅ 84.338µs (SLO: <200.000µs 📉 -57.8%) vs baseline: -0.3% Memory: ✅ 43.969MB (SLO: <46.000MB -4.4%) vs baseline: +5.0% ✅ encode_noaspectTime: ✅ 145.280µs (SLO: <200.000µs 📉 -27.4%) vs baseline: +0.3% Memory: ✅ 44.008MB (SLO: <46.000MB -4.3%) vs baseline: +5.2% ✅ format_aspectTime: ✅ 14.601ms (SLO: <19.200ms 📉 -24.0%) vs baseline: -0.2% Memory: ✅ 43.924MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ format_map_aspectTime: ✅ 16.376ms (SLO: <21.500ms 📉 -23.8%) vs baseline: ~same Memory: ✅ 43.924MB (SLO: <46.000MB -4.5%) vs baseline: +4.6% ✅ format_map_noaspectTime: ✅ 361.761µs (SLO: <500.000µs 📉 -27.6%) vs baseline: +1.5% Memory: ✅ 44.192MB (SLO: <46.000MB -3.9%) vs baseline: +5.3% ✅ format_noaspectTime: ✅ 311.367µs (SLO: <500.000µs 📉 -37.7%) vs baseline: -0.4% Memory: ✅ 43.974MB (SLO: <46.000MB -4.4%) vs baseline: +5.1% ✅ index_aspectTime: ✅ 128.462µs (SLO: <300.000µs 📉 -57.2%) vs baseline: +4.7% Memory: ✅ 43.890MB (SLO: <46.000MB -4.6%) vs baseline: +4.8% ✅ index_noaspectTime: ✅ 40.539µs (SLO: <300.000µs 📉 -86.5%) vs baseline: -0.6% Memory: ✅ 43.939MB (SLO: <46.000MB -4.5%) vs baseline: +5.2% ✅ join_aspectTime: ✅ 216.880µs (SLO: <300.000µs 📉 -27.7%) vs baseline: +1.1% Memory: ✅ 43.940MB (SLO: <46.000MB -4.5%) vs baseline: +4.9% ✅ join_noaspectTime: ✅ 141.052µs (SLO: <300.000µs 📉 -53.0%) vs baseline: -1.0% Memory: ✅ 43.986MB (SLO: <46.000MB -4.4%) vs baseline: +5.1% ✅ ljust_aspectTime: ✅ 585.050µs (SLO: <700.000µs 📉 -16.4%) vs baseline: 📈 +16.6% Memory: ✅ 43.856MB (SLO: <46.000MB -4.7%) vs baseline: +4.8% ✅ ljust_noaspectTime: ✅ 262.086µs (SLO: <300.000µs 📉 -12.6%) vs baseline: +0.7% Memory: ✅ 43.934MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ lower_aspectTime: ✅ 306.346µs (SLO: <500.000µs 📉 -38.7%) vs baseline: -1.2% Memory: ✅ 43.877MB (SLO: <46.000MB -4.6%) vs baseline: +4.7% ✅ lower_noaspectTime: ✅ 241.532µs (SLO: <300.000µs 📉 -19.5%) vs baseline: +2.0% Memory: ✅ 43.869MB (SLO: <46.000MB -4.6%) vs baseline: +4.9% ✅ lstrip_aspectTime: ✅ 0.272ms (SLO: <3.000ms 📉 -90.9%) vs baseline: -1.0% Memory: ✅ 43.943MB (SLO: <46.000MB -4.5%) vs baseline: +5.1% ✅ lstrip_noaspectTime: ✅ 0.179ms (SLO: <3.000ms 📉 -94.0%) vs baseline: +1.0% Memory: ✅ 43.858MB (SLO: <46.000MB -4.7%) vs baseline: +4.9% ✅ modulo_aspectTime: ✅ 14.251ms (SLO: <18.750ms 📉 -24.0%) vs baseline: +0.2% Memory: ✅ 43.843MB (SLO: <46.000MB -4.7%) vs baseline: +4.5% ✅ modulo_aspect_for_bytearray_bytearrayTime: ✅ 14.751ms (SLO: <19.350ms 📉 -23.8%) vs baseline: ~same Memory: ✅ 43.835MB (SLO: <46.000MB -4.7%) vs baseline: +4.4% ✅ modulo_aspect_for_bytesTime: ✅ 14.344ms (SLO: <18.900ms 📉 -24.1%) vs baseline: ~same Memory: ✅ 44.032MB (SLO: <46.000MB -4.3%) vs baseline: +5.0% ✅ modulo_aspect_for_bytes_bytearrayTime: ✅ 14.585ms (SLO: <19.150ms 📉 -23.8%) vs baseline: +0.3% Memory: ✅ 43.930MB (SLO: <46.000MB -4.5%) vs baseline: +4.7% ✅ modulo_noaspectTime: ✅ 0.361ms (SLO: <3.000ms 📉 -88.0%) vs baseline: -1.4% Memory: ✅ 43.929MB (SLO: <46.000MB -4.5%) vs baseline: +4.9% ✅ replace_aspectTime: ✅ 18.384ms (SLO: <24.000ms 📉 -23.4%) vs baseline: +0.5% Memory: ✅ 43.951MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ replace_noaspectTime: ✅ 286.242µs (SLO: <400.000µs 📉 -28.4%) vs baseline: -0.2% Memory: ✅ 43.949MB (SLO: <46.000MB -4.5%) vs baseline: +4.9% ✅ repr_aspectTime: ✅ 324.868µs (SLO: <420.000µs 📉 -22.7%) vs baseline: +0.2% Memory: ✅ 43.891MB (SLO: <46.000MB -4.6%) vs baseline: +4.9% ✅ repr_noaspectTime: ✅ 46.863µs (SLO: <90.000µs 📉 -47.9%) vs baseline: ~same Memory: ✅ 44.013MB (SLO: <46.000MB -4.3%) vs baseline: +5.1% ✅ rstrip_aspectTime: ✅ 386.886µs (SLO: <500.000µs 📉 -22.6%) vs baseline: -0.1% Memory: ✅ 43.918MB (SLO: <46.000MB -4.5%) vs baseline: +5.1% ✅ rstrip_noaspectTime: ✅ 188.049µs (SLO: <300.000µs 📉 -37.3%) vs baseline: +1.7% Memory: ✅ 43.963MB (SLO: <46.000MB -4.4%) vs baseline: +5.2% ✅ slice_aspectTime: ✅ 181.497µs (SLO: <300.000µs 📉 -39.5%) vs baseline: +0.5% Memory: ✅ 43.914MB (SLO: <46.000MB -4.5%) vs baseline: +5.0% ✅ slice_noaspectTime: ✅ 53.777µs (SLO: <90.000µs 📉 -40.2%) vs baseline: -1.3% Memory: ✅ 43.871MB (SLO: <46.000MB -4.6%) vs baseline: +4.9% ✅ stringio_aspectTime: ✅ 4.576ms (SLO: <5.000ms -8.5%) vs baseline: 📈 +18.7% Memory: ✅ 43.914MB (SLO: <46.000MB -4.5%) vs baseline: +5.2% ✅ stringio_noaspectTime: ✅ 356.154µs (SLO: <500.000µs 📉 -28.8%) vs baseline: ~same Memory: ✅ 43.808MB (SLO: <46.000MB -4.8%) vs baseline: +4.7% ✅ strip_aspectTime: ✅ 274.264µs (SLO: <350.000µs 📉 -21.6%) vs baseline: +0.4% Memory: ✅ 44.004MB (SLO: <46.000MB -4.3%) vs baseline: +5.2% ✅ strip_noaspectTime: ✅ 177.784µs (SLO: <240.000µs 📉 -25.9%) vs baseline: +1.0% Memory: ✅ 43.998MB (SLO: <46.000MB -4.4%) vs baseline: +5.2% ✅ swapcase_aspectTime: ✅ 347.719µs (SLO: <500.000µs 📉 -30.5%) vs baseline: ~same Memory: ✅ 43.815MB (SLO: <46.000MB -4.8%) vs baseline: +4.5% ✅ swapcase_noaspectTime: ✅ 272.255µs (SLO: <400.000µs 📉 -31.9%) vs baseline: -1.0% Memory: ✅ 43.971MB (SLO: <46.000MB -4.4%) vs baseline: +5.0% ✅ title_aspectTime: ✅ 335.554µs (SLO: <500.000µs 📉 -32.9%) vs baseline: +1.9% Memory: ✅ 44.029MB (SLO: <46.000MB -4.3%) vs baseline: +5.3% ✅ title_noaspectTime: ✅ 261.704µs (SLO: <400.000µs 📉 -34.6%) vs baseline: -1.6% Memory: ✅ 43.945MB (SLO: <46.000MB -4.5%) vs baseline: +4.8% ✅ translate_aspectTime: ✅ 514.148µs (SLO: <700.000µs 📉 -26.6%) vs baseline: +0.3% Memory: ✅ 43.957MB (SLO: <46.000MB -4.4%) vs baseline: +5.1% ✅ translate_noaspectTime: ✅ 424.591µs (SLO: <500.000µs 📉 -15.1%) vs baseline: -1.3% Memory: ✅ 44.274MB (SLO: <46.000MB -3.8%) vs baseline: +5.6% ✅ upper_aspectTime: ✅ 310.005µs (SLO: <500.000µs 📉 -38.0%) vs baseline: +1.4% Memory: ✅ 43.855MB (SLO: <46.000MB -4.7%) vs baseline: +4.4% ✅ upper_noaspectTime: ✅ 237.798µs (SLO: <400.000µs 📉 -40.6%) vs baseline: ~same Memory: ✅ 43.985MB (SLO: <46.000MB -4.4%) vs baseline: +5.0% 📈 iastaspectsospath - 24/24✅ ospathbasename_aspectTime: ✅ 533.829µs (SLO: <700.000µs 📉 -23.7%) vs baseline: 📈 +27.7% Memory: ✅ 43.936MB (SLO: <46.000MB -4.5%) vs baseline: +4.8% ✅ ospathbasename_noaspectTime: ✅ 426.542µs (SLO: <700.000µs 📉 -39.1%) vs baseline: ~same Memory: ✅ 43.752MB (SLO: <46.000MB -4.9%) vs baseline: +4.6% ✅ ospathjoin_aspectTime: ✅ 627.135µs (SLO: <700.000µs 📉 -10.4%) vs baseline: ~same Memory: ✅ 43.972MB (SLO: <46.000MB -4.4%) vs baseline: +5.2% ✅ ospathjoin_noaspectTime: ✅ 637.514µs (SLO: <700.000µs -8.9%) vs baseline: ~same Memory: ✅ 43.888MB (SLO: <46.000MB -4.6%) vs baseline: +4.9% ✅ ospathnormcase_aspectTime: ✅ 350.894µs (SLO: <700.000µs 📉 -49.9%) vs baseline: +0.2% Memory: ✅ 43.874MB (SLO: <46.000MB -4.6%) vs baseline: +4.8% ✅ ospathnormcase_noaspectTime: ✅ 359.480µs (SLO: <700.000µs 📉 -48.6%) vs baseline: -0.2% Memory: ✅ 43.841MB (SLO: <46.000MB -4.7%) vs baseline: +4.6% ✅ ospathsplit_aspectTime: ✅ 485.689µs (SLO: <700.000µs 📉 -30.6%) vs baseline: +0.2% Memory: ✅ 43.830MB (SLO: <46.000MB -4.7%) vs baseline: +4.7% ✅ ospathsplit_noaspectTime: ✅ 492.659µs (SLO: <700.000µs 📉 -29.6%) vs baseline: +0.3% Memory: ✅ 43.846MB (SLO: <46.000MB -4.7%) vs baseline: +4.6% ✅ ospathsplitdrive_aspectTime: ✅ 368.830µs (SLO: <700.000µs 📉 -47.3%) vs baseline: -0.4% Memory: ✅ 43.894MB (SLO: <46.000MB -4.6%) vs baseline: +4.9% ✅ ospathsplitdrive_noaspectTime: ✅ 72.803µs (SLO: <700.000µs 📉 -89.6%) vs baseline: -0.4% Memory: ✅ 43.891MB (SLO: <46.000MB -4.6%) vs baseline: +4.8% ✅ ospathsplitext_aspectTime: ✅ 458.600µs (SLO: <700.000µs 📉 -34.5%) vs baseline: -0.4% Memory: ✅ 43.821MB (SLO: <46.000MB -4.7%) vs baseline: +4.7% ✅ ospathsplitext_noaspectTime: ✅ 464.167µs (SLO: <700.000µs 📉 -33.7%) vs baseline: ~same Memory: ✅ 43.859MB (SLO: <46.000MB -4.7%) vs baseline: +4.7% 🟡 Near SLO Breach (7 suites)🟡 djangosimple - 28/28✅ appsecTime: ✅ 19.558ms (SLO: <22.300ms 📉 -12.3%) vs baseline: ~same Memory: ✅ 71.457MB (SLO: <73.500MB -2.8%) vs baseline: +4.8% ✅ exception-replay-enabledTime: ✅ 1.365ms (SLO: <1.450ms -5.9%) vs baseline: +0.1% Memory: ✅ 69.658MB (SLO: <71.500MB -2.6%) vs baseline: +4.6% ✅ iastTime: ✅ 19.589ms (SLO: <22.250ms 📉 -12.0%) vs baseline: ~same Memory: ✅ 71.339MB (SLO: <75.000MB -4.9%) vs baseline: +4.6% ✅ profilerTime: ✅ 15.185ms (SLO: <16.550ms -8.2%) vs baseline: -0.5% Memory: ✅ 60.522MB (SLO: <61.000MB 🟡 -0.8%) vs baseline: +4.8% ✅ resource-renamingTime: ✅ 19.522ms (SLO: <21.750ms 📉 -10.2%) vs baseline: ~same Memory: ✅ 71.689MB (SLO: <73.500MB -2.5%) vs baseline: +4.9% ✅ span-code-originTime: ✅ 20.038ms (SLO: <28.200ms 📉 -28.9%) vs baseline: +0.6% Memory: ✅ 71.787MB (SLO: <75.000MB -4.3%) vs baseline: +4.8% ✅ tracerTime: ✅ 19.571ms (SLO: <21.750ms 📉 -10.0%) vs baseline: +0.2% Memory: ✅ 71.759MB (SLO: <75.000MB -4.3%) vs baseline: +5.2% ✅ tracer-and-profilerTime: ✅ 20.997ms (SLO: <23.500ms 📉 -10.7%) vs baseline: +0.1% Memory: ✅ 73.646MB (SLO: <75.000MB 🟡 -1.8%) vs baseline: +5.1% ✅ tracer-dont-create-db-spansTime: ✅ 19.780ms (SLO: <21.500ms -8.0%) vs baseline: +0.5% Memory: ✅ 71.468MB (SLO: <75.000MB -4.7%) vs baseline: +5.0% ✅ tracer-minimalTime: ✅ 17.976ms (SLO: <18.500ms -2.8%) vs baseline: +0.4% Memory: ✅ 71.555MB (SLO: <75.000MB -4.6%) vs baseline: +5.0% ✅ tracer-no-cachesTime: ✅ 18.787ms (SLO: <19.650ms -4.4%) vs baseline: -0.3% Memory: ✅ 71.498MB (SLO: <75.000MB -4.7%) vs baseline: +4.7% ✅ tracer-no-databasesTime: ✅ 20.639ms (SLO: <21.100ms -2.2%) vs baseline: +0.1% Memory: ✅ 71.477MB (SLO: <75.000MB -4.7%) vs baseline: +4.7% ✅ tracer-no-middlewareTime: ✅ 20.777ms (SLO: <21.500ms -3.4%) vs baseline: ~same Memory: ✅ 71.527MB (SLO: <75.000MB -4.6%) vs baseline: +4.9% ✅ tracer-no-templatesTime: ✅ 19.662ms (SLO: <22.000ms 📉 -10.6%) vs baseline: +1.4% Memory: ✅ 71.458MB (SLO: <73.500MB -2.8%) vs baseline: +4.7% 🟡 iastpropagation - 8/8✅ no-propagationTime: ✅ 48.668µs (SLO: <60.000µs 📉 -18.9%) vs baseline: -0.2% Memory: ✅ 41.111MB (SLO: <42.000MB -2.1%) vs baseline: +4.6% ✅ propagation_enabledTime: ✅ 138.150µs (SLO: <190.000µs 📉 -27.3%) vs baseline: +1.2% Memory: ✅ 41.229MB (SLO: <42.000MB 🟡 -1.8%) vs baseline: +5.5% ✅ propagation_enabled_100Time: ✅ 1.583ms (SLO: <2.300ms 📉 -31.2%) vs baseline: ~same Memory: ✅ 41.150MB (SLO: <42.000MB -2.0%) vs baseline: +4.8% ✅ propagation_enabled_1000Time: ✅ 29.355ms (SLO: <34.550ms 📉 -15.0%) vs baseline: +0.3% Memory: ✅ 41.209MB (SLO: <42.000MB 🟡 -1.9%) vs baseline: +5.2% 🟡 otelspan - 22/22✅ add-eventTime: ✅ 41.688ms (SLO: <47.150ms 📉 -11.6%) vs baseline: +0.6% Memory: ✅ 41.675MB (SLO: <47.000MB 📉 -11.3%) vs baseline: +4.7% ✅ add-metricsTime: ✅ 233.990ms (SLO: <344.800ms 📉 -32.1%) vs baseline: -0.8% Memory: ✅ 45.376MB (SLO: <47.500MB -4.5%) vs baseline: +4.3% ✅ add-tagsTime: ✅ 262.437ms (SLO: <330.000ms 📉 -20.5%) vs baseline: -0.7% Memory: ✅ 45.487MB (SLO: <47.500MB -4.2%) vs baseline: +4.7% ✅ get-contextTime: ✅ 81.136ms (SLO: <92.350ms 📉 -12.1%) vs baseline: +0.5% Memory: ✅ 41.209MB (SLO: <46.500MB 📉 -11.4%) vs baseline: +5.0% ✅ is-recordingTime: ✅ 37.925ms (SLO: <44.500ms 📉 -14.8%) vs baseline: ~same Memory: ✅ 41.036MB (SLO: <47.500MB 📉 -13.6%) vs baseline: +4.6% ✅ record-exceptionTime: ✅ 62.894ms (SLO: <67.650ms -7.0%) vs baseline: +0.2% Memory: ✅ 41.684MB (SLO: <47.000MB 📉 -11.3%) vs baseline: +4.9% ✅ set-statusTime: ✅ 43.751ms (SLO: <50.400ms 📉 -13.2%) vs baseline: +0.4% Memory: ✅ 40.910MB (SLO: <47.000MB 📉 -13.0%) vs baseline: +4.6% ✅ startTime: ✅ 38.941ms (SLO: <44.500ms 📉 -12.5%) vs baseline: +4.6% Memory: ✅ 40.999MB (SLO: <47.000MB 📉 -12.8%) vs baseline: +5.0% ✅ start-finishTime: ✅ 89.586ms (SLO: <92.000ms -2.6%) vs baseline: -0.5% Memory: ✅ 38.810MB (SLO: <46.500MB 📉 -16.5%) vs baseline: +4.8% ✅ start-finish-telemetryTime: ✅ 91.444ms (SLO: <93.000ms 🟡 -1.7%) vs baseline: -0.4% Memory: ✅ 38.889MB (SLO: <46.500MB 📉 -16.4%) vs baseline: +4.9% ✅ update-nameTime: ✅ 39.091ms (SLO: <45.150ms 📉 -13.4%) vs baseline: -0.3% Memory: ✅ 41.028MB (SLO: <47.000MB 📉 -12.7%) vs baseline: +4.8% 🟡 packagesupdateimporteddependencies - 24/24 (1 unstable)✅ import_manyTime: ✅ 168.846µs (SLO: <170.000µs 🟡 -0.7%) vs baseline: +0.9% Memory: ✅ 41.260MB (SLO: <46.000MB 📉 -10.3%) vs baseline: +4.4% ✅ import_many_cachedTime: ✅ 131.637µs (SLO: <170.000µs 📉 -22.6%) vs baseline: -0.9% Memory: ✅ 41.012MB (SLO: <46.000MB 📉 -10.8%) vs baseline: +4.3% ✅ import_many_stdlibTime: ✅ 1.258ms (SLO: <1.750ms 📉 -28.1%) vs baseline: +0.8% Memory: ✅ 41.172MB (SLO: <46.000MB 📉 -10.5%) vs baseline: +5.2%
|
…threads Two failure modes are fixed: 1. Hang on awake() after a completed stop()/join(). The previous handshake used a one-shot `_served` Event: the worker set it once on exit and then went away. If awake() ran afterwards it cleared `_served`, signalled the request, and waited for an `_served->set()` that would never come. Because the wait ran with the GIL released, not even a Python-level signal handler could interrupt it; only SIGKILL recovered the process. 2. Deadlock between an in-flight awake() and a periodic callback that calls stop() on its own thread (the Timer._periodic pattern in ddtrace/internal/periodic.py). An earlier fix attempt had stop() acquire `_awake_mutex`, but awake() held that same mutex while waiting on `_served`: the worker-thread stop() then blocked on the mutex before the callback could return and the worker could signal completion — both threads waited forever. Replace the `_served` Event handshake with a `std::condition_variable` (`_awake_cond`) plus `_awake_waiting` / `_awake_served` flags. awake() now waits via `cv::wait`, which releases `_awake_mutex` while blocked, so stop() can synchronize with request publication without deadlocking a worker-thread stop() call. awake() also checks `_stopping && !_skip_shutdown` under the mutex and raises RuntimeError in the permanently-stopped case. `_skip_shutdown` keeps the legitimate `_before_fork()/awake()/_after_fork()` flow working: the restarted worker consumes the queued AWAKE request. The worker only notifies the awake waiter on paths where the request can actually be considered served (AWAKE consumed, or permanent stop/error/finalization exit). A fork-stop deliberately does not notify: the pending AWAKE survives for the worker restarted by `_after_fork()` to serve. Internal API; no release note. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4586038 to
dd5488f
Compare
Description
Sibling to #17632. The native
PeriodicThread.awake()cleared_servedandthen waited on it. When called after
stop()had completed:_servedone last time during cleanup(
_threads.cpp:625) and exited.awake()cleared_servedagain._served->wait()blocked forever.The wait ran inside
AllowThreads(GIL released), so not even a Pythonsignal.alarmhandler could break out —SIGTERMwas ignored and onlySIGKILLwould reap the process.This was surfaced by the periodic-thread lifecycle stress harness (#17633).
Fix
stop()now acquires_awake_mutexaround the_stopping = true+_request->set(STOP)sequence, so it serializes withawake().awake()re-checks_stoppingunder the mutex. If_stopping && !_skip_shutdownthe worker is permanently stopped (not fork-paused) — raise
RuntimeErrorinstead of clearing
_servedand waiting forever._before_fork()→_after_fork()window (which flips_skip_shutdown)still works:
_after_fork()spins up a new worker that consumes the queuedAWAKErequest and sets_served, so queuedawake()calls during forkresume normally. Covered by the existing
test_periodic_thread_preserves_awake_during_restart_window(passes here).Testing
New regression test
test_periodic_awake_after_stop_raises_not_hangsintests/internal/test_periodic.py. All 15 existing tests in that file stillpass:
Standalone verification on a Linux workspace (Python 3.10) — before the fix
the reproducer had to be killed with
SIGKILL; after:Risks
Low. The only behavior change is:
awake()on a thread that has completedstop()+join()now raisesRuntimeErrorinstead of blocking forever. Nolegitimate caller should be relying on the infinite-wait behavior — it was
always a hang.
Internal API;
changelog/no-changelog.Background
Found by the randomized lifecycle stress harness in #17633 while running a
larger-budget soak. The harness occasionally interleaves
stop→awakeand hit the hang;
py-spyshowed the main thread idle at_served->wait()in
awake().🤖 Generated with Claude Code