148 lines
4.9 KiB
Python
Executable File
148 lines
4.9 KiB
Python
Executable File
import os
|
|
import signal
|
|
import time
|
|
|
|
# Suppress harmless but noisy gRPC fork() warnings from pexpect child processes
|
|
os.environ["GRPC_VERBOSITY"] = "NONE"
|
|
os.environ["GRPC_ENABLE_FORK_SUPPORT"] = "0"
|
|
|
|
from connpy import hooks, printer
|
|
from connpy.configfile import configfile
|
|
|
|
PID_FILE1 = "/run/connpy.pid"
|
|
PID_FILE2 = "/tmp/connpy.pid"
|
|
|
|
def _wait_for_termination():
|
|
try:
|
|
while True:
|
|
time.sleep(86400)
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
def stop_api():
|
|
# Read the process ID (pid) from the file
|
|
try:
|
|
with open(PID_FILE1, "r") as f:
|
|
pid = int(f.readline().strip())
|
|
port_line = f.readline().strip()
|
|
port = int(port_line) if port_line else None
|
|
PID_FILE = PID_FILE1
|
|
except (FileNotFoundError, ValueError, OSError):
|
|
try:
|
|
with open(PID_FILE2, "r") as f:
|
|
pid = int(f.readline().strip())
|
|
port_line = f.readline().strip()
|
|
port = int(port_line) if port_line else None
|
|
PID_FILE = PID_FILE2
|
|
except (FileNotFoundError, ValueError, OSError):
|
|
printer.warning("Connpy API server is not running.")
|
|
return None
|
|
# Send a SIGTERM signal to the process
|
|
try:
|
|
os.kill(pid, signal.SIGTERM)
|
|
except OSError as e:
|
|
printer.warning(f"Process kill failed (maybe already dead): {e}")
|
|
# Delete the PID file
|
|
os.remove(PID_FILE)
|
|
printer.info(f"Server with process ID {pid} stopped.")
|
|
return port
|
|
|
|
def debug_api(port=8048, config=None):
|
|
# Check if already running via PID file verification
|
|
for pid_file in [PID_FILE1, PID_FILE2]:
|
|
if os.path.exists(pid_file):
|
|
try:
|
|
with open(pid_file, "r") as f:
|
|
pid = int(f.readline().strip())
|
|
os.kill(pid, 0)
|
|
# If we get here, process exists
|
|
printer.info(f"API is already running (PID {pid})")
|
|
return
|
|
except (ValueError, OSError, ProcessLookupError):
|
|
# Stale PID file, ignore here
|
|
pass
|
|
|
|
# Create PID file for the debug process
|
|
written_pid_file = None
|
|
my_pid = os.getpid()
|
|
try:
|
|
with open(PID_FILE1, "w") as f:
|
|
f.write(str(my_pid) + "\n" + str(port))
|
|
written_pid_file = PID_FILE1
|
|
except OSError:
|
|
try:
|
|
with open(PID_FILE2, "w") as f:
|
|
f.write(str(my_pid) + "\n" + str(port))
|
|
written_pid_file = PID_FILE2
|
|
except OSError:
|
|
pass
|
|
|
|
try:
|
|
from .grpc_layer.server import serve
|
|
conf = config or configfile()
|
|
server = serve(conf, port=port, debug=True)
|
|
printer.info(f"gRPC Server running in debug mode on port {port}...")
|
|
_wait_for_termination()
|
|
server.stop(0)
|
|
from .ai import cleanup
|
|
cleanup()
|
|
finally:
|
|
if written_pid_file and os.path.exists(written_pid_file):
|
|
try:
|
|
os.remove(written_pid_file)
|
|
except OSError:
|
|
pass
|
|
|
|
def start_server(port=8048, config=None):
|
|
try:
|
|
import sys
|
|
# Ensure project root is in path for the child process
|
|
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
if base_dir not in sys.path:
|
|
sys.path.insert(0, base_dir)
|
|
|
|
from connpy.grpc_layer.server import serve
|
|
conf = config or configfile()
|
|
server = serve(conf, port=port, debug=False)
|
|
_wait_for_termination()
|
|
server.stop(0)
|
|
from .ai import cleanup
|
|
cleanup()
|
|
except Exception as e:
|
|
printer.error(f"Background API failed to start: {e}")
|
|
os._exit(1)
|
|
|
|
def start_api(port=8048, config=None):
|
|
# Check if already running via PID file verification
|
|
for pid_file in [PID_FILE1, PID_FILE2]:
|
|
if os.path.exists(pid_file):
|
|
try:
|
|
with open(pid_file, "r") as f:
|
|
pid = int(f.readline().strip())
|
|
os.kill(pid, 0)
|
|
# If we get here, process exists
|
|
printer.info(f"API is already running (PID {pid})")
|
|
return
|
|
except (ValueError, OSError, ProcessLookupError):
|
|
# Stale PID file, ignore here, start_api will overwrite
|
|
pass
|
|
|
|
pid = os.fork()
|
|
if pid == 0:
|
|
# Child process: detached from terminal
|
|
os.setsid()
|
|
start_server(port, config=config)
|
|
else:
|
|
# Parent process: record PID and exit
|
|
try:
|
|
with open(PID_FILE1, "w") as f:
|
|
f.write(str(pid) + "\n" + str(port))
|
|
except OSError:
|
|
try:
|
|
with open(PID_FILE2, "w") as f:
|
|
f.write(str(pid) + "\n" + str(port))
|
|
except OSError:
|
|
printer.error("Couldn't create PID file.")
|
|
exit(1)
|
|
printer.start(f"gRPC Server started with process ID {pid} on port {port}")
|