fix: mismatch WaitGroup

This commit is contained in:
Suyono 2023-12-09 04:29:38 +00:00
parent 9128503da1
commit d5eb872b13
11 changed files with 101 additions and 10 deletions

View File

@ -16,7 +16,8 @@
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
"golang.go" "golang.go",
"ms-azuretools.vscode-docker"
] ]
} }
} }

View File

@ -9,7 +9,8 @@ import (
) )
const ( const (
DummyPath = "/workspaces/wingmate/cmd/experiment/dummy/dummy" // DummyPath = "/workspaces/wingmate/cmd/experiment/dummy/dummy"
DummyPath = "/usr/local/bin/wmdummy"
) )
func main() { func main() {

View File

@ -54,7 +54,7 @@ func Read() (*Config, error) {
} }
} }
if err != nil { if err != nil {
wingmate.Log().Error().Msgf("encounter error when reading service directory %s: %#v", svcdir, err) wingmate.Log().Error().Msgf("encounter error when reading service directory %s: %+v", svcdir, err)
} }
crontabfile = filepath.Join(configPath, CrontabFileName) crontabfile = filepath.Join(configPath, CrontabFileName)
@ -64,7 +64,7 @@ func Read() (*Config, error) {
cronAvailable = true cronAvailable = true
} }
if err != nil { if err != nil {
wingmate.Log().Error().Msgf("encounter error when reading crontab %s: %#v", crontabfile, err) wingmate.Log().Error().Msgf("encounter error when reading crontab %s: %+v", crontabfile, err)
} }
if !serviceAvailable && !cronAvailable { if !serviceAvailable && !cronAvailable {

26
docker/alpine/Dockerfile Normal file
View File

@ -0,0 +1,26 @@
FROM golang:1.21-alpine as builder
ADD . /root/wingmate
WORKDIR /root/wingmate/cmd/wingmate
RUN go build -v
WORKDIR /root/wingmate/cmd/experiment/dummy
RUN go build -v
WORKDIR /root/wingmate/cmd/experiment/starter
RUN go build -v
FROM alpine:3.18
RUN apk add tzdata && ln -s /usr/share/zoneinfo/Australia/Sydney /etc/localtime
COPY --from=builder /root/wingmate/cmd/wingmate/wingmate /usr/local/bin/wingmate
COPY --from=builder /root/wingmate/cmd/experiment/dummy/dummy /usr/local/bin/wmdummy
COPY --from=builder /root/wingmate/cmd/experiment/starter/starter /usr/local/bin/wmstarter
ADD --chmod=755 docker/alpine/entry.sh /usr/local/bin/entry.sh
ADD --chmod=755 docker/alpine/etc /etc
ENTRYPOINT [ "/usr/local/bin/entry.sh" ]
CMD [ "/usr/local/bin/wingmate" ]

7
docker/alpine/entry.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ $# -gt 0 ]; then
exec "$@"
else
exec /usr/local/bin/wingmate
fi

View File

@ -0,0 +1,4 @@
#!/bin/sh
export DUMMY_PATH=/usr/local/bin/wmdummy
exec /usr/local/bin/wmstarter

View File

@ -25,6 +25,10 @@ func (i *Init) service(wg *sync.WaitGroup, path Path, exitFlag <-chan any) {
failStatus bool failStatus bool
) )
defer func() {
wingmate.Log().Info().Str(serviceTag, path.Path()).Msg("stopped")
}()
failStatus = false failStatus = false
service: service:
for { for {
@ -57,7 +61,7 @@ service:
iwg.Wait() iwg.Wait()
if err = cmd.Wait(); err != nil { if err = cmd.Wait(); err != nil {
wingmate.Log().Error().Str(serviceTag, path.Path()).Msgf("got error when waiting: %#v", err) wingmate.Log().Error().Str(serviceTag, path.Path()).Msgf("got error when waiting: %+v", err)
} }
fail: fail:
if failStatus { if failStatus {
@ -84,4 +88,6 @@ func (i *Init) pipeReader(wg *sync.WaitGroup, pipe io.ReadCloser, serviceName st
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
wingmate.Log().Error().Str(serviceTag, serviceName).Msgf("got error when reading pipe: %#v", err) wingmate.Log().Error().Str(serviceTag, serviceName).Msgf("got error when reading pipe: %#v", err)
} }
wingmate.Log().Info().Str(serviceTag, serviceName).Msg("closing pipe")
} }

View File

@ -5,11 +5,16 @@ import (
"os/signal" "os/signal"
"sync" "sync"
"gitea.suyono.dev/suyono/wingmate"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
func (i *Init) sighandler(wg *sync.WaitGroup, trigger chan<- any, selfExit <-chan any) { func (i *Init) sighandler(wg *sync.WaitGroup, trigger chan<- any, selfExit <-chan any) {
defer wg.Wait() defer wg.Done()
defer func() {
wingmate.Log().Warn().Msg("signal handler: exiting")
}()
isOpen := true isOpen := true
@ -23,6 +28,7 @@ signal:
switch s { switch s {
case unix.SIGTERM, unix.SIGINT: case unix.SIGTERM, unix.SIGINT:
if isOpen { if isOpen {
wingmate.Log().Info().Msg("initiating shutdown...")
close(trigger) close(trigger)
wg.Add(1) wg.Add(1)
go i.signalPump(wg, selfExit) go i.signalPump(wg, selfExit)
@ -33,6 +39,7 @@ signal:
} }
case <-selfExit: case <-selfExit:
wingmate.Log().Warn().Msg("signal handler received completion flag")
break signal break signal
} }
} }

View File

@ -4,6 +4,7 @@ import (
"sync" "sync"
"time" "time"
"gitea.suyono.dev/suyono/wingmate"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -15,6 +16,11 @@ const (
) )
func (i *Init) signalPump(wg *sync.WaitGroup, selfExit <-chan any) { func (i *Init) signalPump(wg *sync.WaitGroup, selfExit <-chan any) {
defer wg.Done()
defer func() {
wingmate.Log().Info().Msg("signal pump completed")
}()
if seStatus := i.sigTermPump(time.Now(), selfExit); seStatus == triggered { if seStatus := i.sigTermPump(time.Now(), selfExit); seStatus == triggered {
return return
} }
@ -26,6 +32,11 @@ func (i *Init) sigKillPump(startTime time.Time, selfExit <-chan any) {
t := time.NewTicker(time.Millisecond * 200) t := time.NewTicker(time.Millisecond * 200)
defer t.Stop() defer t.Stop()
wingmate.Log().Info().Msg("start pumping SIGKILL signal")
defer func() {
wingmate.Log().Info().Msg("stop pumping SIGKILL signal")
}()
for time.Since(startTime) < time.Second { for time.Since(startTime) < time.Second {
_ = unix.Kill(-1, unix.SIGKILL) _ = unix.Kill(-1, unix.SIGKILL)
@ -41,6 +52,11 @@ func (i *Init) sigTermPump(startTime time.Time, selfExit <-chan any) status {
t := time.NewTicker(time.Millisecond * 100) t := time.NewTicker(time.Millisecond * 100)
defer t.Stop() defer t.Stop()
wingmate.Log().Info().Msg("start pumping SIGTERM signal")
defer func() {
wingmate.Log().Info().Msg("stop pumping SIGTERM signal")
}()
for time.Since(startTime) < time.Duration(time.Second*4) { for time.Since(startTime) < time.Duration(time.Second*4) {
_ = unix.Kill(-1, unix.SIGTERM) _ = unix.Kill(-1, unix.SIGTERM)

View File

@ -3,7 +3,9 @@ package init
import ( import (
"errors" "errors"
"sync" "sync"
"time"
"gitea.suyono.dev/suyono/wingmate"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -13,13 +15,21 @@ func (i *Init) waiter(wg *sync.WaitGroup, runningFlag <-chan any, sigHandlerFlag
// pid int // pid int
err error err error
running bool running bool
flagged bool
) )
defer wg.Done()
defer func() {
wingmate.Log().Info().Msg("waiter exiting...")
}()
running = true running = true
flagged = true
wait: wait:
for { for {
select { select {
case <-runningFlag: case <-runningFlag:
wingmate.Log().Info().Msg("waiter received shutdown signal...")
running = false running = false
default: default:
} }
@ -27,10 +37,18 @@ wait:
if _, err = unix.Wait4(-1, &ws, 0, nil); err != nil { if _, err = unix.Wait4(-1, &ws, 0, nil); err != nil {
if errors.Is(err, unix.ECHILD) { if errors.Is(err, unix.ECHILD) {
if !running { if !running {
close(sigHandlerFlag) if flagged {
close(sigHandlerFlag)
flagged = false
wingmate.Log().Warn().Msg("waiter: inner flag")
}
wingmate.Log().Warn().Msg("waiter: no child left")
break wait break wait
} }
} }
wingmate.Log().Warn().Msgf("Wait4 returns error: %+v", err)
time.Sleep(time.Millisecond * 100)
} }
} }
} }

View File

@ -2,11 +2,16 @@ package wingmate
import ( import (
"io" "io"
"time"
"gitea.suyono.dev/suyono/wingmate/logger" "gitea.suyono.dev/suyono/wingmate/logger"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
const (
timeTag = "time"
)
var ( var (
w *wrapper w *wrapper
) )
@ -30,15 +35,15 @@ func Log() logger.Log {
} }
func (w *wrapper) Info() logger.Content { func (w *wrapper) Info() logger.Content {
return (*eventWrapper)(w.log.Info()) return (*eventWrapper)(w.log.Info().Time(timeTag, time.Now()))
} }
func (w *wrapper) Warn() logger.Content { func (w *wrapper) Warn() logger.Content {
return (*eventWrapper)(w.log.Warn()) return (*eventWrapper)(w.log.Warn().Time(timeTag, time.Now()))
} }
func (w *wrapper) Error() logger.Content { func (w *wrapper) Error() logger.Content {
return (*eventWrapper)(w.log.Error()) return (*eventWrapper)(w.log.Error().Time(timeTag, time.Now()))
} }
type eventWrapper zerolog.Event type eventWrapper zerolog.Event