From bb8d9fa5ca2c83313f706084080533f0ef1c53a7 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 21 Aug 2024 17:25:19 +0500 Subject: [PATCH] prettify code, fix bugs, make it isolated compile with gcc --- .gitignore | 1 + main.go | 9 ++-- runner/runner.go | 106 +++++++++++++++++++++++++++++++-------- starter/cgroup_prepare.c | 5 +- starter/create_rootfs.sh | 2 +- starter/ns_exec.c | 22 +++++--- starter/starter.c | 7 ++- 7 files changed, 116 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 217cb8b..9ad7717 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /starter/starter /starter/minrootfs /pkg/go/gen +/runs diff --git a/main.go b/main.go index 49ca7ee..24c94a9 100644 --- a/main.go +++ b/main.go @@ -2,13 +2,16 @@ package main import ( runner "git.sch9.ru/new_gate/runner/runner" + "fmt" ) func main() { - err := runner.Init() + runnerService,err := runner.NewRunnerService(); if(err != nil) { panic(err) } - limits := runner.Limits{Core: 3,Memory: 10000000, Time: 1000} - runner.IsolatedRun([]string{"/bin/echo", "123"}, limits) + fmt.Println(runnerService) + runnerService.Build([]string{},""); + //limits := runner.Limits{Core: 3,Memory: 10000000, Time: 1000} + //runner.IsolatedRun([]string{"/bin/echo", "123"}, limits) } diff --git a/runner/runner.go b/runner/runner.go index 2be7f6f..aecea30 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -14,22 +14,57 @@ import ( ) const runIdLength = 20 -var coresIsolated []int type Limits struct { - Core int - Memory int - Time int + Processes int32 + Core int32 + Memory int32 + Time int32 } -func extractNumbers(s string) (result []int) { +const Mib = 1024*1024; +const BuildMemory = 1024*Mib; +const BuildTime = 5000; + +type RunnerService struct { + CoresIsolated []int32 + CoreFreed chan int32 +} + +func genRunId() (runId string) { + for i := 0; i < runIdLength; i++ { + runId += string('a' + byte(rand.Int31n(26))) + } + return +} + +func int32ToString(n int32) string { + return fmt.Sprintf("%d", n) +} + +func copyFile(src string,dst string) error { + log.Println(src,dst) + srcFile,err := os.Open(src) + if(err!=nil) {return err} + defer srcFile.Close() + dstFile,err := os.Create(dst) + if(err!=nil) {return err} + defer dstFile.Close() + _,err = io.Copy(dstFile,srcFile) + if(err!=nil) {return err} + err = dstFile.Sync() + if(err!=nil) {return err} + return nil +} + +func extractNumbers(s string) (result []int32) { lastNumber, isNumber := false,false - var curNumber = 0 + var curNumber int32 = 0 for _, char := range s { isNumber = (char >= '0' && char <= '9') if(isNumber) { curNumber *= 10 - curNumber += int(char - '0') + curNumber += int32(char - '0') } if(!isNumber && lastNumber) { result = append(result, curNumber) @@ -43,13 +78,14 @@ func extractNumbers(s string) (result []int) { return } -func Init() error { +func NewRunnerService() (*RunnerService, error) { + runnerService := RunnerService{make([]int32,0),make(chan int32)} rand.Seed(time.Now().UnixNano()) //croup initialisation: if cgroups.Mode() == cgroups.Unified { log.Println("cgroups v2 usage approved") } else { - return fmt.Errorf("cgroups v2 are not enabled")//TODO: trouble description + return nil,fmt.Errorf("cgroups v2 are not enabled")//TODO: trouble description } //isolated cores initialisation: cmdlineBytes := make([]byte, 400) @@ -59,29 +95,55 @@ func Init() error { kernelParams := strings.Split(cmdline," ") for _, param := range kernelParams{ if(len(param) >= 9 && param[:9] == "isolcpus=") { - coresIsolated = append(coresIsolated, extractNumbers(param[9:])...) + runnerService.CoresIsolated = append(runnerService.CoresIsolated, extractNumbers(param[9:])...) } } - if(len(coresIsolated) == 0) { - return fmt.Errorf("no free cores available")//TODO: trouble description + if(len(runnerService.CoresIsolated) == 0) { + return nil,fmt.Errorf("no free cores available")//TODO: trouble description } - log.Println("running on cores:", coresIsolated) + go func() { + for _,core := range runnerService.CoresIsolated { + runnerService.CoreFreed <- core + } + }() + log.Println("running on cores:", runnerService.CoresIsolated) + //runs directory + os.Mkdir("runs",0777) + os.Chmod("runs",0777) + //complete log.Println("Runner initialisation successful!") - return nil + return &runnerService,nil } -func IsolatedRun(command []string, limits Limits) { - var runId string - for i := 0; i < runIdLength; i++ {runId += string('a' + byte(rand.Int31n(26)))} - os.Mkdir("starter/" + runId, 0777) - args := []string{string(limits.Core), string(limits.Memory), string(limits.Time), runId} +func (runnerService RunnerService) Build(buildCmd []string, filename string) { + core := <-runnerService.CoreFreed + runId := genRunId() + err := os.Mkdir("runs/" + runId, 0777) + if(err!=nil) { log.Fatal(err) } + os.Chmod("runs/" + runId, 0777) + copyFile("starter/shared/main.c","runs/"+runId+"/main.c")//FIXME add source and file extension + runnerService.IsolatedRun([]string{"/usr/bin/gcc","/shared/main.c","-o","/shared/executable","-save-temps=obj"},"../runs/"+runId,Limits{Processes: 10,Core:core,Memory:BuildMemory,Time:BuildTime}); + copyFile("runs/"+runId+"/executable","destination")//FIXME add destination + os.RemoveAll("runs/" + runId) + go func() { + runnerService.CoreFreed <- core + }() +} + +func (runnerService RunnerService) IsolatedRun(command []string, sharedFolder string, limits Limits) { + args := []string{int32ToString(limits.Processes),int32ToString(limits.Core), int32ToString(limits.Memory), int32ToString(limits.Time), sharedFolder} args = append(args, command...) + log.Println(limits.Processes) + log.Println(string(limits.Processes)) + log.Println(args) cmd := exec.Command("starter/starter", args...) var stdBuffer bytes.Buffer mw := io.MultiWriter(os.Stdout, &stdBuffer) cmd.Stdout = mw err := cmd.Run(); - if err != nil { log.Fatal(err) } - os.RemoveAll("starter/" + runId) - cmd.Wait() + if err != nil { + log.Println(123) + log.Println(err) + } + //cmd.Wait() } diff --git a/starter/cgroup_prepare.c b/starter/cgroup_prepare.c index 2283d01..b4404b1 100644 --- a/starter/cgroup_prepare.c +++ b/starter/cgroup_prepare.c @@ -25,7 +25,10 @@ void prepare_cgroup(struct limits* limits) { asprintf(&cpus_string,"%d\n",limits->core); write_file("cpuset.cpus",cpus_string); free(cpus_string); - write_file("pids.max","1\n"); + char* processes_string=NULL; + asprintf(&processes_string,"%d\n",limits->processes); + write_file("pids.max",processes_string); + free(processes_string); //write_file("cpuset.cpus","3\n"); chdir(cwd); } diff --git a/starter/create_rootfs.sh b/starter/create_rootfs.sh index 6bf6e9b..e00dca1 100755 --- a/starter/create_rootfs.sh +++ b/starter/create_rootfs.sh @@ -10,7 +10,7 @@ NAME=minrootfs SCRIPT_DIR=$(dirname -- "$(readlink -f "${BASH_SOURCE}")") rm -rf $SCRIPT_DIR/$NAME -sudo $SCRIPT_DIR/alpine-make-rootfs/alpine-make-rootfs $SCRIPT_DIR/$NAME +$SCRIPT_DIR/alpine-make-rootfs/alpine-make-rootfs --packages 'python3 gcc libc-dev' $SCRIPT_DIR/$NAME #chown -R nobody:nogroup $SCRIPT_DIR/$NAME #rm -r ../$NAME #mv $NAME ../$NAME diff --git a/starter/ns_exec.c b/starter/ns_exec.c index 7f62aff..3e673bd 100644 --- a/starter/ns_exec.c +++ b/starter/ns_exec.c @@ -38,8 +38,8 @@ void ro_fs(char* shared_mountpoint) { char* shared_folder = malloc(strlen(shared_mountpoint)+4); strcpy(shared_folder,"../"); strcat(shared_folder,shared_mountpoint); - if (mount("/","/","ext4",MS_REMOUNT | MS_RDONLY | MS_BIND,"")) die("failed to mount: %m"); - if (mount(shared_mountpoint,"shared","ext4",MS_REMOUNT | MS_RDONLY | MS_BIND,"")) die("failed to mount: %m"); + if (mount("/","/","ext4",MS_REMOUNT | MS_RDONLY| MS_BIND,"")) die("failed to mount: %m"); + if (mount(shared_mountpoint,"shared","ext4",MS_REMOUNT | MS_BIND,"")) die("failed to mount: %m"); free(shared_folder); } //#undef shared_mountpoint @@ -56,11 +56,19 @@ static int nsrun(void* arg) { if (prctl(PR_SET_PDEATHSIG, SIGKILL)) die("cannot PR_SET_PDEATHSIG for child process: %m\n"); struct params *params = (struct params*) arg; await_setup(params->fd[0]); - if(chdir("shared")) die("failed to chdir: %m"); - //int out_fd=open("out",O_WRONLY|O_CREAT); - //if(out_fd==-1) die("unable to open out file:%m"); - //else dup2(out_fd,STDOUT_FILENO); - if(chdir("..")) die("failed to chdir: %m"); + char cwd[PATH_MAX]; + if(getcwd(cwd,sizeof(cwd))==NULL) die("getcwd error: %m"); + if(chdir(params->shared_folder)) die("failed to chdir: %m"); + int out_fd=open("out",O_WRONLY|O_CREAT,0666); + if(out_fd==-1) die("unable to open output file:%m"); + else dup2(out_fd,STDOUT_FILENO); + int in_fd=open("in",O_RDONLY|O_CREAT,0666); + if(in_fd==-1) die("unable to open input file:%m"); + else dup2(in_fd,STDIN_FILENO); + int err_fd=open("err",O_WRONLY|O_CREAT,0666); + if(err_fd==-1) die("unable to open error file:%m"); + else dup2(err_fd,STDERR_FILENO); + if(chdir(cwd)) die("failed to chdir: %m"); mnt_prepare("minrootfs",params->shared_folder); sethostname(hostname,sizeof(hostname)); ro_fs(params->shared_folder); diff --git a/starter/starter.c b/starter/starter.c index b754a4a..ee618c8 100644 --- a/starter/starter.c +++ b/starter/starter.c @@ -28,6 +28,7 @@ struct limits { size_t memory; int core; int time; + int processes; }; struct killparams{ @@ -65,11 +66,13 @@ static char nmstack[STACK_SIZE]; static char killstack[STACK_SIZE]; static void parse_args(int argc, char **argv, struct params *params,struct limits *limits){ - if (argc < 6) { - puts("usage:\n starter