Trace/breakpoint trap

My Linux app is exiting with a Trace/breakpoint trap. This only happens after this function has been called at least 2 or 3 times.

func shell2(_ launchPath: String, _ arguments: [String] = []) -> Bool {
    logProgress("\(#function) : 1")
    var process: Process?
    do {
        process = try Process.run(URL(fileURLWithPath: launchPath), arguments: arguments)
    } catch {
        logError("\(#function) : 2 failed to run")
        return false
    }
    logProgress("\(#function) : 3 after run")
    
    process!.waitUntilExit()
    logProgress("\(#function) : 4 after waitUntilExit")

    if process!.terminationReason == .exit && process!.terminationStatus == 0 {
        logProgress("\(#function) : 5 in the if, so OK")
        return true
    }
    
    logError("\(#function) : 6 failed for another reason")
    return false
}

Console out is:

2022-05-29 16:54:43 - 84 - shell2(_:_:) : 1
2022-05-29 16:54:43 - 85 - shell2(_:_:) : 3 after run
2022-05-29 16:54:43 - 86 - shell2(_:_:) : 4 after waitUntilExit
Trace/breakpoint trap
pirec@satreceiver:~/SatReceiver $

I'm a stuck on this, so any suggestion will be welcome.

Are you running this in a debugger? SIGTRAP is a surprising thing to see if the answer is "no".

For the foreseeable future, everything I run is in degbug mode.

I need to call Process() multiple times to stop and start a binary with updated arguments. Apple say Process() can only be called once - which I translate to mean one instance at a time. I'd been calling it from another place without the waitUntilExit().

So, I've added an & to the bash script.

#!/bin/bash
cd /home/pirec/longmynd/
/usr/bin/sudo /home/pirec/longmynd/longmynd "$1" "$2" "$3" "$4" "$5" > /dev/null 2>&1 &

and now call

shell2("/home/pirec/startLongmynd.sh", params)

I expected this to allow 'shell2()` to return immediately, but it doesn't.

Stopping had always worked as expected

shell2("/usr/bin/sudo", ["/usr/bin/killall", "-w", "longmynd"])

So, I guess the Trace/breakpoint trap was my fault and I need to find a way of getting a Process() to return when launching a background process. Any ideas?

Resorting to bash scripts just feels wrong, so is there a way to do all this natively in Swift?

@lukasa On arm64 that's the normal trap.

@ea7kir This just means that your program crashed because of a fatal error in Swift. Likely that is ! on a nil value, an integer overflow, a fatalError or something else of that kind.

The easiest way to debug what's going is on to either use lldb path/to/your/binary and in lldb type run to run the program and once it crashed, you can look at what's going on, for example with bt which gives you a backtrace.

If you're on macOS, you should also find a crash report that you can look into with Console.app under Crash Reports (left side) name something like yourapp_DATE_TIME....

@lukasa I think I've found a solution. Repeatably executing process = Process() not only solves the problem, it also eliminates the need to call the killall script.

class LongmyndController {
    private let startLongmyndPath = "/home/pirec/startLongmynd.sh"
    private let fifoPath = "/home/pirec/longmynd/longmynd_main_status"
    private var fd: Int32
    private var process: Process
    private var _longmyndIsRunning: Bool
    
    init() {
        self.fd = -1
        self.process = Process()
        self._longmyndIsRunning = false
    }

    var longmyndIsRunning: Bool { get { return _longmyndIsRunning } }

    func configure(with params: [String]) {

        // MARK: stop and start longmynd
        
        process = Process()
        Task {
            process.executableURL = URL(fileURLWithPath: startLongmyndPath)
            process.arguments = params
            do {
                try process.run()
                _longmyndIsRunning = true
            } catch {
                _longmyndIsRunning = false
                logError("LongmyndController.\(#function) : failed to start longmynd")
            }
            
            // MARK: open FIFO - once only and keep it open
            
            if _longmyndIsRunning && fd < 0 {
                fd = open(fifoPath, O_RDONLY)
                if fd < 0 {
                    logError("LongmyndController.\(#function) : failed to open FIFO")
                }
            }
        }
    }

    // other functions follow
}

I ran this in a loop for over an hour without a hiccup, but do you think this dirty solution will cause problems further down the line?

@johannesweiss Debuggers? I've never found the patience to learn one. Trial & error with lots of print statements has always seemed easier, but thank you for your suggestion.