doushihu5475 2014-07-14 04:40
浏览 39
已采纳

goroutines是如何安排的?

I want to use ptrace to trace a process with input and output,so I decide to use exec.Com to start a process instead of os.StartProcess. But something confusing me happened,I am not sure if it is caused by gorountines schedule . I sleep 5 seconds,and send alarm signal every millionsecond but test results show it quickly exits. But If I test with a process running real CPU time,it will pass the test.I find the source code of exec.Com,and there are gorountines to pipe stdin and stdout,which is different from os.StartProcess. If I change to use os.StartProcess , it will pass the test. So I wonder it is something wrong with the gorountines running with sleep. I guess I should do something to lock the sleep to a certain thread,but I not sure what cause the problem.

This is my code:

package sandbox

import (
    "fmt"
    "os"
    "os/exec"
    "runtime"
    "syscall"
    "time"
)

const (
    AC uint64 = iota
    PE
    TLE
    MLE
    WA
    RE
    OLE
    CE
    SE
)

type Tracer struct {
    Process *os.Process
}

func Attach(proc *os.Process) (*Tracer, error) {
    err := syscall.PtraceAttach(proc.Pid)
    if err == syscall.EPERM {
        _, err := syscall.PtraceGetEventMsg(proc.Pid)
        if err != nil {
            return nil, err
        }
    } else if err != nil {
        return nil, err
    }

    return &Tracer{
        Process: proc,
    }, nil
}
func (t *Tracer) Syscall(sig syscall.Signal) error {
    err := syscall.PtraceSyscall(t.Process.Pid, int(sig))
    if err != nil {
        return err
    }
    return nil
}

type RunningObject struct {
    Proc        *os.Process
    TimeLimit   int64
    MemoryLimit int64
    Memory      int64
    Time        int64
    Status      uint64
}

func (r *RunningObject) RunTick(dur time.Duration) {
    ticker := time.NewTicker(dur)
    for _ = range ticker.C {
        r.Proc.Signal(os.Signal(syscall.SIGALRM))
    }
}

func Run(src string, args []string, timeLimit int64, memoryLimit int64) *RunningObject {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    var rusage syscall.Rusage
    var runningObject RunningObject
    runningObject.TimeLimit = timeLimit
    runningObject.MemoryLimit = memoryLimit
    cmd := exec.Command(src, args...)
    err := cmd.Start()
    if err != nil {
        panic(err)
    }
    proc := cmd.Process
    tracer, err := Attach(proc)
    if err != nil {
        panic(err)
    }
    runningObject.Proc = proc
    go runningObject.RunTick(time.Millisecond)
    if err != nil {
        fmt.Println(err)
        return &runningObject
    }
    for {
        status := syscall.WaitStatus(0)
        _, err := syscall.Wait4(proc.Pid, &status, syscall.WSTOPPED, &rusage)
        if err != nil {
            panic(err)
        }
        if status.Exited() {
            fmt.Println("exit")
            return &runningObject
        }
        if status.CoreDump() {
            fmt.Println("CoreDump")
            return &runningObject
        }
        if status.Continued() {
            fmt.Println("Continued")
            return &runningObject
        }
        if status.Signaled() {
            return &runningObject
        }
        if status.Stopped() && status.StopSignal() != syscall.SIGTRAP {
            fmt.Println(status.StopSignal())
        }
        err = tracer.Syscall(syscall.Signal(0))
        if err != nil {
            fmt.Println(err)
        }
    }
}

and this is my test:

package sandbox

import (
    "testing"
)

func TestTime(t *testing.T) {
    obj := Run("/bin/sleep", []string{"sleep", "5"}, 1000, 10000)
    //t.Log(obj.Status)
    if obj.Status != TLE {
        t.Fatal("time exceed test failed.")
    }
}
  • 写回答

1条回答 默认 最新

  • dtv7174 2014-07-14 14:44
    关注

    You don't need to pass arg0 to exec.Command.

    You're giving /bin/sleep the arguments of sleep 5, in which case it exits immediately with the usage text..

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置