fixed tcp/udp I/O, deadlock, nil dereference; improved docker watcher, idlewatcher, loading page

This commit is contained in:
yusing
2024-09-23 00:49:46 +08:00
parent 96bce79e4b
commit 090b73d287
31 changed files with 687 additions and 468 deletions

View File

@@ -3,9 +3,10 @@ package utils
import (
"context"
"encoding/json"
"errors"
"io"
"os"
"sync/atomic"
"syscall"
E "github.com/yusing/go-proxy/error"
)
@@ -16,15 +17,19 @@ type (
Path string
}
ReadCloser struct {
ctx context.Context
r io.ReadCloser
closed atomic.Bool
ContextReader struct {
ctx context.Context
io.Reader
}
ContextWriter struct {
ctx context.Context
io.Writer
}
Pipe struct {
r ReadCloser
w io.WriteCloser
r ContextReader
w ContextWriter
ctx context.Context
cancel context.CancelFunc
}
@@ -35,48 +40,48 @@ type (
}
)
func (r *ReadCloser) Read(p []byte) (int, error) {
func (r *ContextReader) Read(p []byte) (int, error) {
select {
case <-r.ctx.Done():
return 0, r.ctx.Err()
default:
return r.r.Read(p)
return r.Reader.Read(p)
}
}
func (r *ReadCloser) Close() error {
if r.closed.Load() {
return nil
func (w *ContextWriter) Write(p []byte) (int, error) {
select {
case <-w.ctx.Done():
return 0, w.ctx.Err()
default:
return w.Writer.Write(p)
}
r.closed.Store(true)
return r.r.Close()
}
func NewPipe(ctx context.Context, r io.ReadCloser, w io.WriteCloser) *Pipe {
ctx, cancel := context.WithCancel(ctx)
_, cancel := context.WithCancel(ctx)
return &Pipe{
r: ReadCloser{ctx: ctx, r: r},
w: w,
r: ContextReader{ctx: ctx, Reader: r},
w: ContextWriter{ctx: ctx, Writer: w},
ctx: ctx,
cancel: cancel,
}
}
func (p *Pipe) Start() error {
return Copy(p.ctx, p.w, &p.r)
func (p *Pipe) Start() (err error) {
err = Copy(&p.w, &p.r)
switch {
case
// NOTE: ignoring broken pipe and connection reset by peer
errors.Is(err, syscall.EPIPE),
errors.Is(err, syscall.ECONNRESET):
return nil
}
return err
}
func (p *Pipe) Stop() error {
p.cancel()
return E.JoinE("error stopping pipe", p.r.Close(), p.w.Close()).Error()
}
func (p *Pipe) Write(b []byte) (int, error) {
return p.w.Write(b)
}
func NewBidirectionalPipe(ctx context.Context, rw1 io.ReadWriteCloser, rw2 io.ReadWriteCloser) *BidirectionalPipe {
return &BidirectionalPipe{
func NewBidirectionalPipe(ctx context.Context, rw1 io.ReadWriteCloser, rw2 io.ReadWriteCloser) BidirectionalPipe {
return BidirectionalPipe{
pSrcDst: NewPipe(ctx, rw1, rw2),
pDstSrc: NewPipe(ctx, rw2, rw1),
}
@@ -89,7 +94,7 @@ func NewBidirectionalPipeIntermediate(ctx context.Context, listener io.ReadClose
}
}
func (p *BidirectionalPipe) Start() error {
func (p BidirectionalPipe) Start() error {
errCh := make(chan error, 2)
go func() {
errCh <- p.pSrcDst.Start()
@@ -97,20 +102,11 @@ func (p *BidirectionalPipe) Start() error {
go func() {
errCh <- p.pDstSrc.Start()
}()
for err := range errCh {
if err != nil {
return err
}
}
return nil
return E.JoinE("bidirectional pipe error", <-errCh, <-errCh).Error()
}
func (p *BidirectionalPipe) Stop() error {
return E.JoinE("error stopping pipe", p.pSrcDst.Stop(), p.pDstSrc.Stop()).Error()
}
func Copy(ctx context.Context, dst io.WriteCloser, src io.ReadCloser) error {
_, err := io.Copy(dst, &ReadCloser{ctx: ctx, r: src})
func Copy(dst *ContextWriter, src *ContextReader) error {
_, err := io.Copy(dst, src)
return err
}

View File

@@ -4,13 +4,10 @@ import (
"github.com/santhosh-tekuri/jsonschema"
)
var schemaCompiler = func() *jsonschema.Compiler {
c := jsonschema.NewCompiler()
c.Draft = jsonschema.Draft7
return c
}()
var schemaStorage = make(map[string]*jsonschema.Schema)
var (
schemaCompiler = jsonschema.NewCompiler()
schemaStorage = make(map[string]*jsonschema.Schema)
)
func GetSchema(path string) *jsonschema.Schema {
if schema, ok := schemaStorage[path]; ok {