Open SeRG1k17 opened 3 months ago
@SeRG1k17 thanks for reaching out. I will take a look into this ASAP and get back to you.
Hey @SeRG1k17 I was not able to replicate the issue you are facing (please see: https://github.com/dominicegginton/spinner/blob/duration-debug/Sources/DebugDuration/main.swift where I have created an example to debug)
import Spinner
import Foundation
@discardableResult
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
let message = "duration debugging - running sleep cmd"
let spinner = Spinner(.dots, message, format: "{S} {T} ⏱️ {D}")
spinner.start()
shell("sleep", "10") // do work
spinner.stop()
Running my example I got the expected result (including duration updates as time progresses):
Please can you provide more information about the environment you are building on and the call to the function shell.run
provided example? This may give me more ideas on what could be the problem here.
I managed to get a time greater than 0 seconds, this happens when the command hangs and works for a very long time. It seems more than 1 minute, same on CI. I will try create a sample soon
//ShellService.swift
func run(
_ command: String,
message: String = "",
silentOutput: Bool = false
) throws -> String {
let spinner = Spinner(.dots, message, format: "{S} {T} ⏱️ {D}")
spinner.start()
let process = Process()
process.arguments = ["-c", command]
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
process.launchPath = "/bin/bash"
let outputPipe = Pipe()
process.standardOutput = outputPipe
let errorPipe = Pipe()
process.standardError = errorPipe
var outputData = Data()
var errorData = Data()
let outputQueue = DispatchQueue(label: "process-output-queue")
outputPipe.fileHandleForReading.readabilityHandler = { handler in
outputQueue.async {
outputData.append(handler.availableData)
if !silentOutput {
self.logService.standartOutput(handler.availableData)
}
}
}
errorPipe.fileHandleForReading.readabilityHandler = { handler in
outputQueue.async {
errorData.append(handler.availableData)
if !silentOutput {
self.logService.standartOutput(handler.availableData)
}
}
}
do {
try process.run()
} catch {
spinner.error(error.localizedDescription)
// logService.log(error.localizedDescription, logLevel: .debug)
throw error
}
logService.log("command: '\(command)'".blue, logLevel: .debug)
process.waitUntilExit()
outputPipe.fileHandleForReading.readabilityHandler = nil
errorPipe.fileHandleForReading.readabilityHandler = nil
return try outputQueue.sync {
if process.terminationStatus == EXIT_SUCCESS {
spinner.success()
return try outputData.string
} else {
spinner.error()
if let errorString = try? errorData.string, !errorString.isEmpty {
throw Error.custom(errorString)
} else {
throw Error.runtime(reason: process.terminationReason)
}
}
}
}
Hello @dominicegginton, Looks like the issue reproduces only on Apple Silicon. I guess there is something wrong with DispatchTime.now there, so it would be great if you could change it to clock_gettime_nsec_np or something.
//Output:
I checked your code and it looks correct, you calculate the value between the start and the current time each time. However, the value does not change
Thank you for good project!