Skip to content

Commit

Permalink
Basic window support in subprocess mode
Browse files Browse the repository at this point in the history
  • Loading branch information
michurin committed Jun 11, 2024
1 parent 4b6556e commit 7e49950
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 53 deletions.
53 changes: 0 additions & 53 deletions cmd/pplog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,59 +110,6 @@ func prepareFormatters() (func([]slogtotext.Pair) error, func([]slogtotext.Pair)
return slogtotext.MustFormatter(os.Stdout, logLine), slogtotext.MustFormatter(os.Stdout, errLine)
}

func runSubprocessMode() {
deb("run subprocess mode")

target := flag.Args()
binary, err := exec.LookPath(target[0])
if err != nil {
panic(err)
}

r, w, err := os.Pipe()
if err != nil {
panic(err)
}

chFiles := make([]uintptr, 3) // in, out, err
chFiles[0] = r.Fd()
chFiles[1] = os.Stdout.Fd()
chFiles[2] = os.Stderr.Fd()

selfBinaty, err := exec.LookPath(os.Args[0])
if err != nil {
panic(err)
}
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
pid, err := syscall.ForkExec(selfBinaty, os.Args[:1], &syscall.ProcAttr{
Dir: cwd,
Env: os.Environ(),
Files: chFiles,
Sys: nil,
})
if err != nil {
panic(selfBinaty + ": " + err.Error())
}
deb(fmt.Sprintf("subprocess pid: %d", pid))

err = syscall.Dup2(int(w.Fd()), syscall.Stdout) // os.Stdout = w
if err != nil {
panic(err)
}
err = syscall.Dup2(int(w.Fd()), syscall.Stderr) // os.Stderr = w
if err != nil {
panic(err)
}

err = syscall.Exec(binary, target, os.Environ())
if err != nil {
panic(binary + ": " + err.Error())
}
}

func runPipeMode() {
deb("run pipe mode")
f, g := prepareFormatters()
Expand Down
65 changes: 65 additions & 0 deletions cmd/pplog/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//go:build !windows
// +build !windows

package main

import (
"flag"
"fmt"
"os"
"os/exec"
"syscall"
)

func runSubprocessMode() {
deb("run subprocess mode")

target := flag.Args()
binary, err := exec.LookPath(target[0])
if err != nil {
panic(err)
}

r, w, err := os.Pipe()
if err != nil {
panic(err)
}

chFiles := make([]uintptr, 3) //nolint:mnd // in, out, err
chFiles[0] = r.Fd()
chFiles[1] = os.Stdout.Fd()
chFiles[2] = os.Stderr.Fd()

selfBinaty, err := exec.LookPath(os.Args[0])
if err != nil {
panic(err)
}
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
pid, err := syscall.ForkExec(selfBinaty, os.Args[:1], &syscall.ProcAttr{
Dir: cwd,
Env: os.Environ(),
Files: chFiles,
Sys: nil,
})
if err != nil {
panic(selfBinaty + ": " + err.Error())
}
deb(fmt.Sprintf("subprocess pid: %d", pid))

err = syscall.Dup2(int(w.Fd()), syscall.Stdout) // os.Stdout = w
if err != nil {
panic(err)
}
err = syscall.Dup2(int(w.Fd()), syscall.Stderr) // os.Stderr = w
if err != nil {
panic(err)
}

err = syscall.Exec(binary, target, os.Environ())
if err != nil {
panic(binary + ": " + err.Error())
}
}
50 changes: 50 additions & 0 deletions cmd/pplog/run_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//go:build windows
// +build windows

package main

import (
"context"
"flag"
"io"
"os"
"os/exec"

"github.com/michurin/human-readable-json-logging/slogtotext"
)

func runSubprocessMode() {
deb("run subprocess mode (windows)")

ctx := context.Background()

rd, wr := io.Pipe()

f, g := prepareFormatters()
go func() {
err := slogtotext.Read(rd, f, g, 32768)
if err != nil {
deb("reader is finished with err: " + err.Error())
return
}
deb("reader is finished")
}()

args := flag.Args()[1:]
command := flag.Args()[0]

cmd := exec.CommandContext(ctx, command, args...)
cmd.Stdout = wr
cmd.Stderr = wr

err := cmd.Run()
deb("subprocess is finished")
if err != nil {
printError(err)
}
exitCode := cmd.ProcessState.ExitCode() // exit code can be set even if error
if exitCode < 0 {
exitCode = 1
}
os.Exit(exitCode)
}

0 comments on commit 7e49950

Please # to comment.