fix: add launcher script to wrap langflow startup (#8884)
* Add launcher script to wrap langflow startup * [autofix.ci] apply automated fixes * Ruff * [autofix.ci] apply automated fixes * ruff * [autofix.ci] apply automated fixes * rut pusff * [autofix.ci] apply automated fixes * use exec instead of subprocess * [autofix.ci] apply automated fixes * Remove forced run addition to cli * Integrate Typer for improved error handling in langflow launcher --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
parent
db48cd38cd
commit
56ff3e12f6
3 changed files with 130 additions and 110 deletions
51
src/backend/base/langflow/langflow_launcher.py
Normal file
51
src/backend/base/langflow/langflow_launcher.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import typer
|
||||
|
||||
|
||||
def main():
|
||||
"""Launches langflow with appropriate environment setup.
|
||||
|
||||
On macOS, sets required environment variables and replaces current process.
|
||||
On other platforms, calls main function directly.
|
||||
"""
|
||||
if platform.system() == "Darwin": # macOS
|
||||
_launch_with_exec()
|
||||
else:
|
||||
# On non-macOS systems, call the main function directly
|
||||
from langflow.__main__ import main as langflow_main
|
||||
|
||||
langflow_main()
|
||||
|
||||
|
||||
def _launch_with_exec():
|
||||
"""Launch langflow by replacing current process with properly configured environment.
|
||||
|
||||
This approach is necessary because Objective-C libraries are preloaded by the Python
|
||||
runtime before any Python code executes. Setting OBJC_DISABLE_INITIALIZE_FORK_SAFETY
|
||||
within Python code is too late - it must be set in the parent process environment
|
||||
before spawning Python.
|
||||
|
||||
Testing with OBJC_PRINT_INITIALIZE=YES confirms that NSCheapMutableString and
|
||||
other Objective-C classes are initialized during Python startup, before any
|
||||
user code runs. This causes fork safety issues when gunicorn or multiprocessing
|
||||
attempts to fork the process.
|
||||
|
||||
The exec approach sets the environment variables and then replaces the current
|
||||
process with a new Python process. This is more efficient than subprocess since
|
||||
we don't need the launcher process to remain running, and signals are handled
|
||||
directly by the target process.
|
||||
"""
|
||||
# Set environment variables before exec
|
||||
os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES"
|
||||
# Additional fix for gunicorn compatibility
|
||||
os.environ["no_proxy"] = "*"
|
||||
|
||||
try:
|
||||
os.execv(sys.executable, [sys.executable, "-m", "langflow.__main__"] + sys.argv[1:]) # noqa: S606
|
||||
except OSError as e:
|
||||
# If exec fails, we need to exit since the process replacement failed
|
||||
typer.echo(f"Failed to exec langflow: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue