wait with timeout + correct error processing

This commit is contained in:
Egor Aristov 2025-11-16 06:59:52 +03:00
parent 5b52490495
commit 2c6429065b
Signed by: egor3f
GPG Key ID: 40482A264AAEC85F
3 changed files with 42 additions and 19 deletions

View File

@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"path"
"time"
kittenipc "efprojects.com/kitten-ipc"
)
@ -59,9 +60,9 @@ func main() {
if err != nil {
log.Panic(err)
}
log.Printf("remote call result = %v", res)
log.Printf("remote call result from ts = %v", res)
if err := ipc.Wait(); err != nil {
if err := ipc.Wait(1 * time.Second); err != nil {
log.Panic(err)
}
}

View File

@ -20,7 +20,7 @@ async function main() {
await ipc.start();
console.log(`remote call result = ${await remoteApi.Div(10, 2)}`);
console.log(`remote call result from go = ${await remoteApi.Div(10, 2)}`);
await ipc.wait();
}

View File

@ -350,22 +350,27 @@ func (p *ParentIPC) Stop() error {
}
p.stopRequested.Store(true)
if err := p.cmd.Process.Signal(syscall.SIGINT); err != nil {
return fmt.Errorf("send SIGTERM: %w", err)
return fmt.Errorf("send SIGINT: %w", err)
}
return p.Wait()
}
func (p *ParentIPC) Wait() error {
func (p *ParentIPC) Wait(timeout ...time.Duration) (retErr error) {
waitErrCh := make(chan error, 1)
const defaultTimeout = time.Duration(1<<63 - 1) // max duration in go
_timeout := variadicToOption(timeout).OrElse(defaultTimeout)
go func() {
waitErrCh <- p.cmd.Wait()
}()
var retErr error
loop:
for {
select {
case err := <-p.errCh:
retErr = fmt.Errorf("ipc internal error: %w", err)
retErr = mergeErr(retErr, fmt.Errorf("ipc internal error: %w", err))
break loop
case err := <-waitErrCh:
if err != nil {
var exitErr *exec.ExitError
@ -373,11 +378,18 @@ func (p *ParentIPC) Wait() error {
if !exitErr.Success() {
ws, ok := exitErr.Sys().(syscall.WaitStatus)
if !(ok && ws.Signaled() && ws.Signal() == syscall.SIGINT && p.stopRequested.Load()) {
retErr = fmt.Errorf("cmd wait: %w", err)
retErr = mergeErr(retErr, fmt.Errorf("cmd wait: %w", err))
}
}
} else {
retErr = fmt.Errorf("cmd wait: %w", err)
retErr = mergeErr(retErr, fmt.Errorf("cmd wait: %w", err))
}
}
break loop
case <-time.After(_timeout):
p.stopRequested.Store(true)
if err := p.cmd.Process.Signal(syscall.SIGINT); err != nil {
retErr = mergeErr(retErr, fmt.Errorf("send SIGINT: %w", err))
}
}
}
@ -450,3 +462,13 @@ func mapTypeNames(types []any) map[string]any {
}
return result
}
func variadicToOption[T any](variadic []T) mo.Option[T] {
if len(variadic) >= 2 {
panic("variadic param count must be 0 or 1")
}
if len(variadic) == 0 {
return mo.None[T]()
}
return mo.Some(variadic[0])
}