mirror of
https://github.com/criyle/go-judge.git
synced 2025-11-04 14:50:02 +08:00
fix windows build
This commit is contained in:
parent
a439711540
commit
d06968e152
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -42,164 +41,6 @@ func (e *execServer) Exec(ctx context.Context, req *pb.Request) (*pb.Response, e
|
|||||||
return convertPBResponse(rt), nil
|
return convertPBResponse(rt), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *execServer) ExecStream(es pb.Executor_ExecStreamServer) error {
|
|
||||||
msg, err := es.Recv()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req := msg.GetExecRequest()
|
|
||||||
if req == nil {
|
|
||||||
return fmt.Errorf("The first stream request must be exec request")
|
|
||||||
}
|
|
||||||
rq, streamIn, streamOut, err := convertPBRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
for _, fi := range streamIn {
|
|
||||||
fi.Close()
|
|
||||||
}
|
|
||||||
for _, fi := range streamOut {
|
|
||||||
fi.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
errCh := make(chan error, 1)
|
|
||||||
|
|
||||||
// stream in
|
|
||||||
if len(streamIn) > 0 {
|
|
||||||
go func() {
|
|
||||||
err := streamInput(es, streamIn)
|
|
||||||
if err != nil {
|
|
||||||
writeErrCh(errCh, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// stream out
|
|
||||||
outCh := make(chan *pb.StreamResponse_ExecOutput, len(streamOut))
|
|
||||||
if len(streamOut) > 0 {
|
|
||||||
for _, so := range streamOut {
|
|
||||||
so := so
|
|
||||||
go func() {
|
|
||||||
err := streamOutput(es.Context().Done(), outCh, so)
|
|
||||||
if err != nil {
|
|
||||||
writeErrCh(errCh, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rtCh := work.Execute(es.Context(), rq)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case err := <-errCh:
|
|
||||||
return err
|
|
||||||
|
|
||||||
case o := <-outCh:
|
|
||||||
err = es.Send(&pb.StreamResponse{
|
|
||||||
Response: o,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buffPool.Put(o.ExecOutput.Content[:cap(o.ExecOutput.Content)])
|
|
||||||
|
|
||||||
case rt := <-rtCh:
|
|
||||||
execObserve(rt)
|
|
||||||
if rt.Error != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return es.Send(&pb.StreamResponse{
|
|
||||||
Response: &pb.StreamResponse_ExecResponse{
|
|
||||||
ExecResponse: convertPBResponse(rt),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func streamOutput(done <-chan struct{}, outCh chan<- *pb.StreamResponse_ExecOutput, so *fileStreamOut) error {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := buffPool.Get().([]byte)
|
|
||||||
n, err := so.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
outCh <- &pb.StreamResponse_ExecOutput{
|
|
||||||
ExecOutput: &pb.StreamResponse_Output{
|
|
||||||
Name: so.Name(),
|
|
||||||
Content: buf[:n],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func streamInput(es pb.Executor_ExecStreamServer, streamIn []*fileStreamIn) error {
|
|
||||||
inf := make(map[string]*fileStreamIn)
|
|
||||||
for _, f := range streamIn {
|
|
||||||
inf[f.Name()] = f
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-es.Context().Done():
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
in, err := es.Recv()
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch i := in.Request.(type) {
|
|
||||||
case *pb.StreamRequest_ExecInput:
|
|
||||||
f, ok := inf[i.ExecInput.GetName()]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("input %s not exists", i.ExecInput.GetName())
|
|
||||||
}
|
|
||||||
_, err = f.Write(i.ExecInput.Content)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("write to input %s with err %w", i.ExecInput.GetName(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
case *pb.StreamRequest_ExecResize:
|
|
||||||
f, ok := inf[i.ExecResize.GetName()]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("input %s not exists", i.ExecResize.GetName())
|
|
||||||
}
|
|
||||||
winSize := &pty.Winsize{
|
|
||||||
Rows: uint16(i.ExecResize.Rows),
|
|
||||||
Cols: uint16(i.ExecResize.Cols),
|
|
||||||
X: uint16(i.ExecResize.X),
|
|
||||||
Y: uint16(i.ExecResize.Y),
|
|
||||||
}
|
|
||||||
err = pty.Setsize(f.w, winSize)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("resize to input %s with err %w", i.ExecResize.GetName(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("the following request must be input request")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeErrCh(ch chan error, err error) {
|
|
||||||
select {
|
|
||||||
case ch <- err:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *execServer) FileList(c context.Context, n *pb.Empty) (*pb.FileListType, error) {
|
func (e *execServer) FileList(c context.Context, n *pb.Empty) (*pb.FileListType, error) {
|
||||||
return &pb.FileListType{
|
return &pb.FileListType{
|
||||||
FileIDs: e.fs.List(),
|
FileIDs: e.fs.List(),
|
||||||
|
|||||||
167
cmd/executorserver/grpc_linux.go
Normal file
167
cmd/executorserver/grpc_linux.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/creack/pty"
|
||||||
|
"github.com/criyle/go-judge/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *execServer) ExecStream(es pb.Executor_ExecStreamServer) error {
|
||||||
|
msg, err := es.Recv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req := msg.GetExecRequest()
|
||||||
|
if req == nil {
|
||||||
|
return fmt.Errorf("The first stream request must be exec request")
|
||||||
|
}
|
||||||
|
rq, streamIn, streamOut, err := convertPBRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
for _, fi := range streamIn {
|
||||||
|
fi.Close()
|
||||||
|
}
|
||||||
|
for _, fi := range streamOut {
|
||||||
|
fi.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
|
// stream in
|
||||||
|
if len(streamIn) > 0 {
|
||||||
|
go func() {
|
||||||
|
err := streamInput(es, streamIn)
|
||||||
|
if err != nil {
|
||||||
|
writeErrCh(errCh, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// stream out
|
||||||
|
outCh := make(chan *pb.StreamResponse_ExecOutput, len(streamOut))
|
||||||
|
if len(streamOut) > 0 {
|
||||||
|
for _, so := range streamOut {
|
||||||
|
so := so
|
||||||
|
go func() {
|
||||||
|
err := streamOutput(es.Context().Done(), outCh, so)
|
||||||
|
if err != nil {
|
||||||
|
writeErrCh(errCh, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtCh := work.Execute(es.Context(), rq)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-errCh:
|
||||||
|
return err
|
||||||
|
|
||||||
|
case o := <-outCh:
|
||||||
|
err = es.Send(&pb.StreamResponse{
|
||||||
|
Response: o,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buffPool.Put(o.ExecOutput.Content[:cap(o.ExecOutput.Content)])
|
||||||
|
|
||||||
|
case rt := <-rtCh:
|
||||||
|
execObserve(rt)
|
||||||
|
if rt.Error != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return es.Send(&pb.StreamResponse{
|
||||||
|
Response: &pb.StreamResponse_ExecResponse{
|
||||||
|
ExecResponse: convertPBResponse(rt),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamOutput(done <-chan struct{}, outCh chan<- *pb.StreamResponse_ExecOutput, so *fileStreamOut) error {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := buffPool.Get().([]byte)
|
||||||
|
n, err := so.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
outCh <- &pb.StreamResponse_ExecOutput{
|
||||||
|
ExecOutput: &pb.StreamResponse_Output{
|
||||||
|
Name: so.Name(),
|
||||||
|
Content: buf[:n],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamInput(es pb.Executor_ExecStreamServer, streamIn []*fileStreamIn) error {
|
||||||
|
inf := make(map[string]*fileStreamIn)
|
||||||
|
for _, f := range streamIn {
|
||||||
|
inf[f.Name()] = f
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-es.Context().Done():
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
in, err := es.Recv()
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch i := in.Request.(type) {
|
||||||
|
case *pb.StreamRequest_ExecInput:
|
||||||
|
f, ok := inf[i.ExecInput.GetName()]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("input %s not exists", i.ExecInput.GetName())
|
||||||
|
}
|
||||||
|
_, err = f.Write(i.ExecInput.Content)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write to input %s with err %w", i.ExecInput.GetName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *pb.StreamRequest_ExecResize:
|
||||||
|
f, ok := inf[i.ExecResize.GetName()]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("input %s not exists", i.ExecResize.GetName())
|
||||||
|
}
|
||||||
|
winSize := &pty.Winsize{
|
||||||
|
Rows: uint16(i.ExecResize.Rows),
|
||||||
|
Cols: uint16(i.ExecResize.Cols),
|
||||||
|
X: uint16(i.ExecResize.X),
|
||||||
|
Y: uint16(i.ExecResize.Y),
|
||||||
|
}
|
||||||
|
err = pty.Setsize(f.w, winSize)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("resize to input %s with err %w", i.ExecResize.GetName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("the following request must be input request")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeErrCh(ch chan error, err error) {
|
||||||
|
select {
|
||||||
|
case ch <- err:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user