mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
restore simple child terminator
This commit is contained in:
parent
3c72384084
commit
aa87b2905f
1 changed files with 22 additions and 67 deletions
|
|
@ -128,7 +128,7 @@ final class BunServer {
|
||||||
|
|
||||||
// Create the process using login shell
|
// Create the process using login shell
|
||||||
let process = Process()
|
let process = Process()
|
||||||
process.executableURL = URL(fileURLWithPath: binaryPath)
|
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
||||||
|
|
||||||
// Get the Resources directory path
|
// Get the Resources directory path
|
||||||
let resourcesPath = Bundle.main.resourcePath ?? Bundle.main.bundlePath
|
let resourcesPath = Bundle.main.resourcePath ?? Bundle.main.bundlePath
|
||||||
|
|
@ -175,14 +175,30 @@ final class BunServer {
|
||||||
logger.info("Local authentication bypass enabled for Mac app")
|
logger.info("Local authentication bypass enabled for Mac app")
|
||||||
}
|
}
|
||||||
|
|
||||||
process.arguments = vibetunnelArgs
|
// Create wrapper to run vibetunnel with parent death monitoring
|
||||||
|
let parentPid = ProcessInfo.processInfo.processIdentifier
|
||||||
|
let vibetunnelCommand = """
|
||||||
|
# Start vibetunnel in background
|
||||||
|
\(binaryPath) \(vibetunnelArgs.joined(separator: " ")) &
|
||||||
|
VIBETUNNEL_PID=$!
|
||||||
|
|
||||||
|
# Monitor parent process
|
||||||
|
while kill -0 \(parentPid) 2>/dev/null; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Parent died, kill vibetunnel
|
||||||
|
kill -TERM $VIBETUNNEL_PID 2>/dev/null
|
||||||
|
wait $VIBETUNNEL_PID
|
||||||
|
"""
|
||||||
|
process.arguments = ["-l", "-c", vibetunnelCommand]
|
||||||
|
|
||||||
// Set up a termination handler for logging
|
// Set up a termination handler for logging
|
||||||
process.terminationHandler = { [weak self] process in
|
process.terminationHandler = { [weak self] process in
|
||||||
self?.logger.info("vibetunnel process terminated with status: \(process.terminationStatus)")
|
self?.logger.info("vibetunnel process terminated with status: \(process.terminationStatus)")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Executing command: \(binaryPath) \(vibetunnelArgs.joined(separator: " "))")
|
logger.info("Executing command: /bin/zsh -l -c \"\(vibetunnelCommand)\"")
|
||||||
logger.info("Binary location: \(resourcesPath)")
|
logger.info("Binary location: \(resourcesPath)")
|
||||||
|
|
||||||
// Set up a minimal environment for the SEA binary
|
// Set up a minimal environment for the SEA binary
|
||||||
|
|
@ -240,12 +256,12 @@ final class BunServer {
|
||||||
var errorDetails = "Exit code: \(exitCode)"
|
var errorDetails = "Exit code: \(exitCode)"
|
||||||
if let stderrPipe = self.stderrPipe {
|
if let stderrPipe = self.stderrPipe {
|
||||||
do {
|
do {
|
||||||
let errorData = try stderrPipe.fileHandleForReading.readDataToEndOfFile()
|
if let errorData = try stderrPipe.fileHandleForReading.readToEnd(),
|
||||||
if !errorData.isEmpty, let errorOutput = String(data: errorData, encoding: .utf8) {
|
!errorData.isEmpty,
|
||||||
|
let errorOutput = String(data: errorData, encoding: .utf8) {
|
||||||
errorDetails += "\nError: \(errorOutput.trimmingCharacters(in: .whitespacesAndNewlines))"
|
errorDetails += "\nError: \(errorOutput.trimmingCharacters(in: .whitespacesAndNewlines))"
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// File handle might be invalid if process exited immediately
|
|
||||||
logger.debug("Could not read stderr: \(error.localizedDescription)")
|
logger.debug("Could not read stderr: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -594,67 +610,6 @@ enum BunServerError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Process Extensions
|
|
||||||
|
|
||||||
extension Process {
|
|
||||||
/// Run the process asynchronously
|
|
||||||
func runAsync() async throws {
|
|
||||||
try await withCheckedThrowingContinuation { continuation in
|
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
|
||||||
do {
|
|
||||||
try self.run()
|
|
||||||
continuation.resume()
|
|
||||||
} catch {
|
|
||||||
continuation.resume(throwing: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wait for the process to exit asynchronously
|
|
||||||
func waitUntilExitAsync() async {
|
|
||||||
await withCheckedContinuation { continuation in
|
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
|
||||||
self.waitUntilExit()
|
|
||||||
continuation.resume()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Terminate the process asynchronously
|
|
||||||
func terminateAsync() async {
|
|
||||||
await withCheckedContinuation { continuation in
|
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
|
||||||
if self.isRunning {
|
|
||||||
self.terminate()
|
|
||||||
}
|
|
||||||
continuation.resume()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wait for exit with timeout
|
|
||||||
func waitUntilExitWithTimeout(seconds: TimeInterval) async -> Bool {
|
|
||||||
await withTaskGroup(of: Bool.self) { group in
|
|
||||||
group.addTask {
|
|
||||||
await self.waitUntilExitAsync()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
group.addTask {
|
|
||||||
try? await Task.sleep(for: .seconds(seconds))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for await result in group {
|
|
||||||
group.cancelAll()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - LogHandler
|
// MARK: - LogHandler
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue