Skip to content

Support use of Python subprocesses in bundled apps #3078

Closed

Description

@freakboy3742

Describe the bug

A desktop app bundled with Briefcase is unable to spawn a subprocess that uses sys.executable. This prohibits some notable use cases, including multiprocessing.

How to reproduce the bug

Run a program that includes an button on_press handler that invokes subprocess.run([sys.executable, ...])

When the subprocess is executed, a second copy of the application will start.

Minimum example code

import subprocess
import sys


def on_press(widget, **kwargs):
    result = subprocess.run([sys.executable, "-c", "print(f'hello subprocess')"])

Screenshots

No response

Environment details

  • Operating system and version: All desktop OS
  • Python version: All (tested recently on 3.13)
  • Software versions:
    • Briefcase: 0.3+ (tested recently on 0.4.5)
    • Toga: 0.5.7

Logs


Additional context

This issue has been long standing; see:

There has been some recent movement on this issue:

Activity

  1. freakboy3742 commented on Oct 2, 2026

    @freakboy3742
    MemberAuthor

    I've tested the in-progress PRs (many thanks to @abdnh for that) - and they work great... with one side effect.

    The PRs are based on re-writing sys.executable to point at an actual Python binary. Historically, we have stripped python.exe from the packaged app; the proposed fix is to add an allow_subprocesses option that will not strip the binary, and modifies sys.executable in the app's interpreter. We shouldn't include python.exe in all apps, as it is a full Python interpreter (which represents a very attractive attack surface); but there are enough uses for multiprocessing et al that it's worth including as an option.

    The complication is that Toga currently uses the name of sys.executable to determine:

    • the app icon on Windows, GTK and Qt,
    • Whether the app is "bundled" (i.e., is this a Briefcase app)

    If we rewrite sys.executable, those techniques break.

    We can modify how Toga operates - see beeware/toga#4742 for a PR that modifies Toga to use sys.orig_argv[0] instead of sys.executable. However, we can't fix that retroactively.

    So - we have a decision to make. The options, as I see them:

    0. Do nothing

    Status quo; and we declare multiprocessing as officially unsupported. Not a very satisfying option, but it's an option.

    1. Accept short-term breakage in subprocess-using Toga apps

    Merge #3077 and the template changes; release Briefcase 0.4.6. Merge beeware/toga#4742.

    Existing Briefcase apps won't change. However, it won't be possible to use the new feature until there's a Toga release that includes the beeware/toga#4742 change - based on normal schedule, that would be in December.

    It's unclear how this will affect non-Toga apps. The default Qt and PySide CE apps both start without any problem, but it's impossible to know what usage of sys.executable exists in the wild.

    2. Release a fixed Toga

    Same as 1, but we also push out an early Toga release as well so there's a Toga release that will work with the new Briefcase feature.

    Again, existing apps won't change; but Toga apps will have a path to using the new feature as long as they adopt Toga 0.5.8 as a minimum. This would be the default for any freshly generated app, but adding subprocess support to an existing app might need a bump to Toga version pins. However, that's fully opt in, so it's a safe option.

    3. Add a safety catch

    Same as 2, but we plan to also add a safety catch for allow_subprocesses = False apps that try to invoke sys.executable. If we set sys.executable = None if the app has allow_subprocesses = False, the failure mode is a lot more pleasant - you don't get a spawned second copy of the app - you get a TypeError because subprocess.run() doesn't accept None as the first argument.

    This would be a great safety mechanism for any user who tries to call subprocess.run([sys.executable, ...]) *without* using allow_subprocesses` in their Briefcase configuration. I managed to fork-bomb myself more than once in testing this subprocess handling; that strikes me as something we should protect against if we can.

    However, we can't do it it immediately, because any existing Toga app would break with the new Briefcase version. There would be a fix - update your Toga version - but that's not something we can easily enforce without making a special case of Toga in Briefcase's code. So - we defer making this change for 6-12 months to give people a chance to update their Toga apps "organically" before they're forced to update.

    4. Add a safety catch now

    Same as 3, but we add the safety catch now, and document the requirement. Users either don't upgrade Briefcase, or must upgrade Toga.


    I'm not sure which option is best - 4 is the best outcome and easiest to implement, but I'm unsure if it leans on people reading release notes a little too much.

    Any thoughts?

  2. abdnh commented on Oct 2, 2026

    @abdnh
    Contributor

    What if we implement a safety catch in the form of detecting if the app is trying to run the stub binary as a Python subprocess?
    Similar to my previous approach in beeware/briefcase-windows-VisualStudio-template#128 but with the difference that we fail with an error instead of running Py_RunMain().

  3. mhsmith commented on Oct 3, 2026

    @mhsmith
    Member

    This would be a great safety mechanism for any user who tries to call subprocess.run([sys.executable, ...]) without using allow_subprocesses` in their Briefcase configuration. I managed to fork-bomb myself more than once

    I agree; there's a lot of code in the wild that's at risk of doing that.

    any existing Toga app would break with the new Briefcase version.

    The sys.executable documentation also mentions an empty string as a possible value. That should allow old Toga versions to give the correct result from is_bundled, though I don't know what would happen with the icon code.

    If the only effect is that the combination of an old Toga and a new Briefcase would lose the app icon, I think that's acceptable, as long as it appears in the Deprecations and Removals section of the release notes.

    If it would be more convenient, we could also delay merging this until after the upcoming Briefcase release, so both Briefcase and Toga would release their changes at the same time in December.

  4. freakboy3742 commented on Oct 5, 2026

    @freakboy3742
    MemberAuthor

    The sys.executable documentation also mentions an empty string as a possible value. That should allow old Toga versions to give the correct result from is_bundled, though I don't know what would happen with the icon code.

    Ah - that's actually much better, for two reasons:

    1. It doesn't break is_bundled on historical Toga installs
    2. subprocess.run([""]) raises a PermissionError, which is a more meaningful error response than TypeError (which is what a subprocess.run([None]) generates).

    We'd still need to update toga.App.is_bundled because in new code, sys.executable will point at python.exe in bundled code - but at least it won't break historical installs.

    If the only effect is that the combination of an old Toga and a new Briefcase would lose the app icon, I think that's acceptable, as long as it appears in the Deprecations and Removals section of the release notes.

    As far as I can make out, this is the only impact - and even then, only on Windows and Linux. macOS uses a native bundle API, so changing sys.executable doesn't impact things.

    If it would be more convenient, we could also delay merging this until after the upcoming Briefcase release, so both Briefcase and Toga would release their changes at the same time in December.

    I guess that's the easy approach - defer landing this for a week or so, make it the first new feature in the next Briefcase release, and then release both Toga and Briefcase in December.

  5. freakboy3742 commented on Oct 5, 2026

    @freakboy3742
    MemberAuthor

    I've updated the stub apps to use "" for sys.executable; I've added a removal note to #3077 indicating the change to sys.executable handling; and I've moved beeware/toga#4742 out of draft mode.

    At this point, we can wait until the Briefcase release next week, land the Briefcase and template PRs, and re-tag the stub binaries on Windows and macOS. Toga was released last week, so beeware/toga#4742 can be landed at any time.

  6. moved this from In progress to Done in BeeWare Planningon Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA crash or error in behavior.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions