Beispiel #1
0
func TestCurrentDir(t *testing.T) {
	pids := ListPids()

	if len(pids) < 1 {
		t.Error("Unable to list process IDs")
	}

	foundCurrent := false
	for _, pid := range pids {
		proc, err := GetProcInfo(pid)
		if err == nil {
			if len(proc.CurrentDir) == 0 {
				t.Errorf("GetProcInfo returned no error for %d but failed to read current dir", pid)
			}
		}

		if pid == syscall.Getpid() {
			foundCurrent = true
			currentDir, _ := os.Getwd()
			if currentDir != proc.CurrentDir {
				t.Errorf("expected working dir for current process %s, got %s", currentDir, proc.CurrentDir)
			}
		}
	}

	if !foundCurrent {
		t.Errorf("Current process %d not among listed processes", syscall.Getpid())
	}
}
Beispiel #2
0
// Test that basic signal handling works.
func TestSignal(t *testing.T) {
	// Ask for hangup
	c := make(chan os.Signal, 1)
	Notify(c, syscall.Note("hangup"))
	defer Stop(c)

	// Send this process a hangup
	t.Logf("hangup...")
	postNote(syscall.Getpid(), "hangup")
	waitSig(t, c, syscall.Note("hangup"))

	// Ask for everything we can get.
	c1 := make(chan os.Signal, 1)
	Notify(c1)

	// Send this process an alarm
	t.Logf("alarm...")
	postNote(syscall.Getpid(), "alarm")
	waitSig(t, c1, syscall.Note("alarm"))

	// Send two more hangups, to make sure that
	// they get delivered on c1 and that not reading
	// from c does not block everything.
	t.Logf("hangup...")
	postNote(syscall.Getpid(), "hangup")
	waitSig(t, c1, syscall.Note("hangup"))
	t.Logf("hangup...")
	postNote(syscall.Getpid(), "hangup")
	waitSig(t, c1, syscall.Note("hangup"))

	// The first SIGHUP should be waiting for us on c.
	waitSig(t, c, syscall.Note("hangup"))
}
Beispiel #3
0
func TestSighupHandler(t *testing.T) {
	ranHandler := make(chan bool, 1)
	handler := func(d daemon.Daemon) {
		ranHandler <- true
	}
	conf, _ := config.New("example.yaml")
	d, _ := daemon.New(conf)
	setupSighupHandler(d, handler)
	// Need to sleep here so that the goroutine has time to set up the signal listener, otherwise
	// the signal gets missed
	time.Sleep(1 * time.Second)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)

	// Give the syscall 1 second to be handled, should be more than enough time
	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(time.Duration(1 * time.Second))
		timeout <- true
	}()
	select {
	case <-ranHandler:
	case <-timeout:
		t.Fatal("Didn't run handler")
	}

	// Try calling again and make sure it still happens
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	select {
	case <-ranHandler:
	case <-timeout:
		t.Fatal("Didn't run handler second time")
	}
}
Beispiel #4
0
// Test that basic signal handling works.
func TestSignal(t *testing.T) {
	// Ask for SIGHUP
	c := make(chan os.Signal, 1)
	Notify(c, syscall.SIGHUP)
	defer Stop(c)

	// Send this process a SIGHUP
	t.Logf("sighup...")
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	waitSig(t, c, syscall.SIGHUP)

	// Ask for everything we can get.
	c1 := make(chan os.Signal, 1)
	Notify(c1)

	// Send this process a SIGWINCH
	t.Logf("sigwinch...")
	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
	waitSig(t, c1, syscall.SIGWINCH)

	// Send two more SIGHUPs, to make sure that
	// they get delivered on c1 and that not reading
	// from c does not block everything.
	t.Logf("sighup...")
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	waitSig(t, c1, syscall.SIGHUP)
	t.Logf("sighup...")
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	waitSig(t, c1, syscall.SIGHUP)

	// The first SIGHUP should be waiting for us on c.
	waitSig(t, c, syscall.SIGHUP)
}
Beispiel #5
0
func main() {
	var i int
	fmt.Scanf("%d", &i)
	if i == 0 {
		fmt.Println(syscall.Getpid())
		syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	}
	fmt.Println("-----------")
}
Beispiel #6
0
/*
Serve accepts incoming HTTP connections on the listener l, creating a new
service goroutine for each. The service goroutines read requests and then call
handler to reply to them. Handler is typically nil, in which case the
DefaultServeMux is used.

In addition to the stl Serve behaviour each connection is added to a
sync.Waitgroup so that all outstanding connections can be served before shutting
down the server.
*/
func (srv *endlessServer) Serve() (err error) {
	defer log.Println(syscall.Getpid(), "Serve() returning...")
	srv.state = STATE_RUNNING
	err = srv.Server.Serve(srv.EndlessListener)
	log.Println(syscall.Getpid(), "Waiting for connections to finish...")
	srv.wg.Wait()
	srv.state = STATE_TERMINATE
	return
}
Beispiel #7
0
func start(c *cli.Context) {
	if pidfile != "" {
		pid, err := fileOrPid(pidfile)
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			os.Exit(1)
		}
		if pid != 0 && pid != syscall.Getppid() {
			fmt.Fprintf(os.Stderr, "There is already a pidfile at '%s' that appears to belong to another apiplexy instance.")
			os.Exit(1)
		}
	}

	if configPath == "" {
		configPath = c.String("config")
	}

	ap, config, err := initApiplex(configPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}

	server := &http.Server{
		Addr:           "0.0.0.0:" + strconv.Itoa(config.Serve.Port),
		Handler:        ap,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 16,
	}

	fmt.Printf("Launching apiplexy on port %d.\n", config.Serve.Port)
	l, err := net.Listen("tcp", server.Addr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't start server on %s: %s\n", server.Addr, err.Error())
		os.Exit(1)
	}

	// write pidfile and wait for restart signal
	if pidfile != "" {
		ioutil.WriteFile(pidfile, []byte(strconv.Itoa(syscall.Getpid())), 0600)
	}

	defer func() {
		// server shuts down, delete pidfile if it's still our PID in there
		if pidfile != "" {
			rp, _ := ioutil.ReadFile(pidfile)
			p, _ := strconv.Atoi(string(rp))
			if p == syscall.Getpid() {
				os.Remove(pidfile)
			}
		}
	}()

	server.Serve(l)
}
Beispiel #8
0
func Test_Handle_With2_SIGHUP_ExecutesFnTwice(t *testing.T) {
	done := make(chan bool, 1)
	signal.Handle(func() {
		done <- true
	})
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	receiveOnce(t, done)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	receiveOnce(t, done)
}
Beispiel #9
0
/*
Serve accepts incoming HTTP connections on the listener l, creating a new
service goroutine for each. The service goroutines read requests and then call
handler to reply to them. Handler is typically nil, in which case the
DefaultServeMux is used.

In addition to the stl Serve behaviour each connection is added to a
sync.Waitgroup so that all outstanding connections can be served before shutting
down the server.
*/
func (srv *endlessServer) Serve() (err error) {
	defer log.Println(syscall.Getpid(), "Serve() returning...")
	srv.setState(STATE_RUNNING)
	err = srv.Server.Serve(srv.EndlessListener)
	log.Println(syscall.Getpid(), "Waiting for connections to finish...")
	srv.waitTimeout(2 * time.Second)
	log.Println(syscall.Getpid(), "Connections termiated")
	srv.setState(STATE_TERMINATE)
	return
}
Beispiel #10
0
func testCancel(t *testing.T, ignore bool) {
	// Send SIGWINCH. By default this signal should be ignored.
	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
	time.Sleep(100 * time.Millisecond)

	// Ask to be notified on c1 when a SIGWINCH is received.
	c1 := make(chan os.Signal, 1)
	Notify(c1, syscall.SIGWINCH)
	defer Stop(c1)

	// Ask to be notified on c2 when a SIGHUP is received.
	c2 := make(chan os.Signal, 1)
	Notify(c2, syscall.SIGHUP)
	defer Stop(c2)

	// Send this process a SIGWINCH and wait for notification on c1.
	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
	waitSig(t, c1, syscall.SIGWINCH)

	// Send this process a SIGHUP and wait for notification on c2.
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	waitSig(t, c2, syscall.SIGHUP)

	// Ignore, or reset the signal handlers for, SIGWINCH and SIGHUP.
	if ignore {
		Ignore(syscall.SIGWINCH, syscall.SIGHUP)
	} else {
		Reset(syscall.SIGWINCH, syscall.SIGHUP)
	}

	// Send this process a SIGWINCH. It should be ignored.
	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)

	// If ignoring, Send this process a SIGHUP. It should be ignored.
	if ignore {
		syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
	}

	select {
	case s := <-c1:
		t.Fatalf("unexpected signal %v", s)
	case <-time.After(100 * time.Millisecond):
		// nothing to read - good
	}

	select {
	case s := <-c2:
		t.Fatalf("unexpected signal %v", s)
	case <-time.After(100 * time.Millisecond):
		// nothing to read - good
	}

	// Reset the signal handlers for all signals.
	Reset()
}
Beispiel #11
0
// Acquire an exclusive lock for the BlobStore in directory dir.
func acquireLockfile(path string) os.Error {
	dir, fn := filepath.Split(path)
	lockfn := filepath.Join(dir, fn)

	lockfile, err := os.OpenFile(lockfn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
	if e, ok := err.(*os.PathError); ok && e.Error == os.EEXIST {
		content, err := ioutil.ReadFile(lockfn)
		if err != nil {
			return err
		}

		pid, err := strconv.Atoi(string(content))
		if err == nil {
			errno := syscall.Kill(pid, 0)
			if errno == 0 {
				return ErrLocked
			}
		}

		lockfile, err = ioutil.TempFile(dir, "lock")
		if err != nil {
			return err
		}

		_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
		if err != nil {
			lockfile.Close()
			return ErrLockAcquirement
		}

		curfn := lockfile.Name()

		err = lockfile.Close()
		if err != nil {
			return err
		}

		err = os.Rename(curfn, lockfn)
		if err != nil {
			os.Remove(curfn)
			return ErrLockAcquirement
		}
	} else if err != nil {
		return err
	} else {
		_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
		if err != nil {
			return err
		}
		lockfile.Close()
	}

	return nil
}
Beispiel #12
0
// Test that Stop cancels the channel's registrations.
func TestStop(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	sigs := []string{
		"alarm",
		"hangup",
	}

	for _, sig := range sigs {
		// Send the signal.
		// If it's alarm, we should not see it.
		// If it's hangup, maybe we'll die. Let the flag tell us what to do.
		if sig != "hangup" {
			postNote(syscall.Getpid(), sig)
		}
		time.Sleep(100 * time.Millisecond)

		// Ask for signal
		c := make(chan os.Signal, 1)
		Notify(c, syscall.Note(sig))
		defer Stop(c)

		// Send this process that signal
		postNote(syscall.Getpid(), sig)
		waitSig(t, c, syscall.Note(sig))

		Stop(c)
		select {
		case s := <-c:
			t.Fatalf("unexpected signal %v", s)
		case <-time.After(100 * time.Millisecond):
			// nothing to read - good
		}

		// Send the signal.
		// If it's alarm, we should not see it.
		// If it's hangup, maybe we'll die. Let the flag tell us what to do.
		if sig != "hangup" {
			postNote(syscall.Getpid(), sig)
		}

		select {
		case s := <-c:
			t.Fatalf("unexpected signal %v", s)
		case <-time.After(100 * time.Millisecond):
			// nothing to read - good
		}
	}
}
Beispiel #13
0
/*
Serve accepts incoming HTTP connections on the listener l, creating a new
service goroutine for each. The service goroutines read requests and then call
handler to reply to them. Handler is typically nil, in which case the
DefaultServeMux is used.

In addition to the stl Serve behaviour each connection is added to a
sync.Waitgroup so that all outstanding connections can be served before shutting
down the server.
*/
func (srv *endlessServer) Serve() (err error) {
	defer log.Println(syscall.Getpid(), "Serve() returning...")
	srv.state = STATE_RUNNING
	err = srv.Server.Serve(srv.EndlessListener)
	if opErr, ok := err.(*net.OpError); ok {
		// This is hacky, but unfortunately the net package doesn't export errClosing
		if strings.Contains(opErr.Error(), "use of closed network connection") {
			err = nil
		}
	}
	log.Println(syscall.Getpid(), "Waiting for connections to finish...")
	srv.wg.Wait()
	srv.state = STATE_TERMINATE
	return
}
Beispiel #14
0
// Test that Stop cancels the channel's registrations.
func TestStop(t *testing.T) {
	sigs := []syscall.Signal{
		syscall.SIGWINCH,
		syscall.SIGHUP,
		syscall.SIGUSR1,
	}

	for _, sig := range sigs {
		// Send the signal.
		// If it's SIGWINCH, we should not see it.
		// If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
		if sig == syscall.SIGWINCH || (sig == syscall.SIGHUP && *sendUncaughtSighup == 1) {
			syscall.Kill(syscall.Getpid(), sig)
		}
		time.Sleep(100 * time.Millisecond)

		// Ask for signal
		c := make(chan os.Signal, 1)
		Notify(c, sig)
		defer Stop(c)

		// Send this process that signal
		syscall.Kill(syscall.Getpid(), sig)
		waitSig(t, c, sig)

		Stop(c)
		select {
		case s := <-c:
			t.Fatalf("unexpected signal %v", s)
		case <-time.After(100 * time.Millisecond):
			// nothing to read - good
		}

		// Send the signal.
		// If it's SIGWINCH, we should not see it.
		// If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
		if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 {
			syscall.Kill(syscall.Getpid(), sig)
		}

		select {
		case s := <-c:
			t.Fatalf("unexpected signal %v", s)
		case <-time.After(100 * time.Millisecond):
			// nothing to read - good
		}
	}
}
Beispiel #15
0
func main() {
	pid := syscall.Getpid()
	flag.Parse()

	// create the pipeline
	pipeline := falcore.NewPipeline()
	pipeline.Upstream.PushBack(falcore.NewRequestFilter(Filter))

	// create the server with the pipeline
	srv := falcore.NewServer(8090, pipeline)

	// if passed the socket file descriptor, setup the listener that way
	// if you don't have it, the default is to create the socket listener
	// with the data passed to falcore.NewServer above (happens in ListenAndServer())
	if *socketFd != -1 {
		// I know I'm a child process if I get here so I can signal the parent when I'm ready to take over
		go childReady(srv)
		fmt.Printf("%v Got socket FD: %v\n", pid, *socketFd)
		srv.FdListen(*socketFd)
	}

	// using signals to manage the restart lifecycle
	go handleSignals(srv)

	// start the server
	// this is normally blocking forever unless you send lifecycle commands
	fmt.Printf("%v Starting Listener on 8090\n", pid)
	if err := srv.ListenAndServe(); err != nil {
		fmt.Printf("%v Could not start server: %v", pid, err)
	}
	fmt.Printf("%v Exiting now\n", pid)
}
Beispiel #16
0
func saveHeapProfiles() {
	runtime.MemProfileRate = 1
	var memstats, prevMemstats runtime.MemStats

	t0 := time.Now()
	for t := range time.NewTicker(250 * time.Millisecond).C {
		startms := int(t.Sub(t0).Seconds() * 1000)
		runtime.ReadMemStats(&memstats)
		if memstats.HeapInuse > prevMemstats.HeapInuse {
			fd, err := os.Create(fmt.Sprintf("heap-%05d-%07d.pprof", syscall.Getpid(), startms))
			if err != nil {
				panic(err)
			}
			err = pprof.WriteHeapProfile(fd)
			if err != nil {
				panic(err)
			}
			err = fd.Close()
			if err != nil {
				panic(err)
			}
			prevMemstats = memstats
		}
	}
}
/*
	Invoke BigDataScript java program

	WARNING:
		It is assumed that BigDataScript.jar is in the same executable binary as 'bds'

		This is actually a nice hack used to distribute only one file. Since JAR files
		are actually ZIP files and ZIP files are indexed from the end of the file, you can
		append the JAR to the go binary (cat binary jar > new_binary) and you encapsulate
		both in the same file.

		Idea and implementation of this hack: Hernan Gonzalez
*/
func bigDataScript() int {
	// Create a taskLoggerFile (temp file based on pid number)
	prefix := "bds.pid." + strconv.Itoa(syscall.Getpid())
	pidTmpFile, err := tempFile(prefix)
	if err != nil {
		log.Fatal(err)
	}
	taskLoggerFile = pidTmpFile
	defer os.Remove(taskLoggerFile) // Make sure the PID file is removed

	// Append all arguments from command line
	args := []string{"java",
		"-Xmx2G",
		"-cp", execName,
		"ca.mcgill.mcb.pcingola.bigDataScript.BigDataScript"}
	args = append(args, "-pid")
	args = append(args, taskLoggerFile)
	for _, arg := range os.Args[1:] {
		args = append(args, arg)
	}

	// Execute command
	exitCode := executeCommand("java", args, 0, "", "", "")

	return exitCode
}
Beispiel #18
0
/*
	Invoke bds java program

	WARNING:
		It is assumed that bds.jar is in the same executable binary as 'bds'

		This is actually a nice hack used to distribute only one file. Since JAR files
		are actually ZIP files and ZIP files are indexed from the end of the file, you can
		append the JAR to the go binary (cat binary jar > new_binary) and you encapsulate
		both in the same file.

		Idea and implementation of this hack: Hernan Gonzalez
*/
func (be *BdsExec) Bds() int {
	// Create a taskLoggerFile (temp file based on pid number)
	prefix := "bds.pid." + strconv.Itoa(syscall.Getpid())
	pidTmpFile, err := tmpfile.TempFile(prefix)
	if err != nil {
		log.Fatal(err)
	}
	be.taskLoggerFile = pidTmpFile
	defer os.Remove(be.taskLoggerFile) // Make sure the PID file is new
	if DEBUG {
		log.Printf("Info: taskLoggerFile '%s'\n", be.taskLoggerFile)
	}

	bdsLibDir := path.Dir(be.execName) + "/" + BDS_NATIVE_LIB_DIR

	// Append all arguments from command line
	be.cmdargs = []string{JAVA_CMD,
		JAVA_MEM,
		JAVA_NATIVE_LIB + bdsLibDir,
		"-cp", be.execName,
		JAVA_BDS_CLASS}
	be.cmdargs = append(be.cmdargs, "-pid")
	be.cmdargs = append(be.cmdargs, be.taskLoggerFile)
	for _, arg := range be.args[1:] {
		be.cmdargs = append(be.cmdargs, arg)
	}

	// Execute command
	be.command = JAVA_CMD
	exitCode := be.executeCommand()

	return exitCode
}
Beispiel #19
0
func TestHandleInterrupts(t *testing.T) {
	for _, sig := range []syscall.Signal{syscall.SIGINT, syscall.SIGTERM} {
		n := 1
		RegisterInterruptHandler(func() { n++ })
		RegisterInterruptHandler(func() { n *= 2 })

		c := make(chan os.Signal, 2)
		signal.Notify(c, sig)

		HandleInterrupts()
		syscall.Kill(syscall.Getpid(), sig)

		// we should receive the signal once from our own kill and
		// a second time from HandleInterrupts
		waitSig(t, c, sig)
		waitSig(t, c, sig)

		if n == 3 {
			t.Fatalf("interrupt handlers were called in wrong order")
		}
		if n != 4 {
			t.Fatalf("interrupt handlers were not called properly")
		}
		// reset interrupt handlers
		interruptHandlers = interruptHandlers[:0]
		interruptExitMu.Unlock()
	}
}
Beispiel #20
0
// NewEvaler creates a new Evaler.
func NewEvaler(st *store.Store) *Evaler {
	// Construct searchPaths
	var searchPaths []string
	if path := os.Getenv("PATH"); path != "" {
		searchPaths = strings.Split(path, ":")
	} else {
		searchPaths = []string{"/bin"}
	}

	// Construct initial global namespace
	pid := String(strconv.Itoa(syscall.Getpid()))
	paths := NewList()
	paths.appendStrings(searchPaths)
	global := Namespace{
		"pid":   NewPtrVariable(pid),
		"ok":    NewPtrVariable(OK),
		"true":  NewPtrVariable(Bool(true)),
		"false": NewPtrVariable(Bool(false)),
		"paths": NewPtrVariable(paths),
	}
	for _, b := range builtinFns {
		global[FnPrefix+b.Name] = NewPtrVariable(b)
	}

	return &Evaler{global, map[string]Namespace{}, searchPaths, st}
}
Beispiel #21
0
func TestRuleAddAndLoad(t *testing.T) {
	// Test #1: Add a trivial filter
	filter1, err := NewFilter(ActAllow)
	if err != nil {
		t.Errorf("Error creating filter: %s", err)
	}
	defer filter1.Release()

	call, err := GetSyscallFromName("getpid")
	if err != nil {
		t.Errorf("Error getting syscall number of getpid: %s", err)
	}

	call2, err := GetSyscallFromName("setreuid")
	if err != nil {
		t.Errorf("Error getting syscall number of setreuid: %s", err)
	}

	uid := syscall.Getuid()
	euid := syscall.Geteuid()

	err = filter1.AddRule(call, ActErrno.SetReturnCode(0x1))
	if err != nil {
		t.Errorf("Error adding rule to restrict syscall: %s", err)
	}

	cond, err := MakeCondition(1, CompareEqual, uint64(euid))
	if err != nil {
		t.Errorf("Error making rule to restrict syscall: %s", err)
	}

	cond2, err := MakeCondition(0, CompareEqual, uint64(uid))
	if err != nil {
		t.Errorf("Error making rule to restrict syscall: %s", err)
	}

	conditions := []ScmpCondition{cond, cond2}

	err = filter1.AddRuleConditional(call2, ActErrno.SetReturnCode(0x2), conditions)
	if err != nil {
		t.Errorf("Error adding conditional rule: %s", err)
	}

	err = filter1.Load()
	if err != nil {
		t.Errorf("Error loading filter: %s", err)
	}

	// Try making a simple syscall, it should error
	pid := syscall.Getpid()
	if pid != -1 {
		t.Errorf("Syscall should have returned error code!")
	}

	// Try making a Geteuid syscall that should normally succeed
	err = syscall.Setreuid(uid, euid)
	if err != syscall.Errno(2) {
		t.Errorf("Syscall should have returned error code!")
	}
}
Beispiel #22
0
func TestNewEvaler(t *testing.T) {
	ev := NewEvaler(nil, "")
	pid := strconv.Itoa(syscall.Getpid())
	if toString(ev.builtin["pid"].Get()) != pid {
		t.Errorf(`ev.builtin["pid"] = %v, want %v`, ev.builtin["pid"], pid)
	}
}
Beispiel #23
0
// Test that SIGCONT works (issue 8953).
func TestSIGCONT(t *testing.T) {
	c := make(chan os.Signal, 1)
	Notify(c, syscall.SIGCONT)
	defer Stop(c)
	syscall.Kill(syscall.Getpid(), syscall.SIGCONT)
	waitSig(t, c, syscall.SIGCONT)
}
Beispiel #24
0
// Handle lifecycle events
func handleSignals(srv *falcore.Server) {
	var sig os.Signal
	var sigChan = make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGINT, syscall.SIGTERM, syscall.SIGTSTP)
	pid := syscall.Getpid()
	for {
		sig = <-sigChan
		switch sig {
		case syscall.SIGHUP:
			// send this to the paraent process to initiate the restart
			fmt.Println(pid, "Received SIGHUP.  forking.")
			cpid, err := forker(srv)
			fmt.Println(pid, "Forked pid:", cpid, "errno:", err)
		case syscall.SIGUSR1:
			// child sends this back to the parent when it's ready to Accept
			fmt.Println(pid, "Received SIGUSR1.  Stopping accept.")
			srv.StopAccepting()
		case syscall.SIGINT:
			fmt.Println(pid, "Received SIGINT.  Shutting down.")
			os.Exit(0)
		case syscall.SIGTERM:
			fmt.Println(pid, "Received SIGTERM.  Terminating.")
			os.Exit(0)
		case syscall.SIGTSTP:
			fmt.Println(pid, "Received SIGTSTP.  Stopping.")
			syscall.Kill(pid, syscall.SIGSTOP)
		default:
			fmt.Println(pid, "Received", sig, ": ignoring")
		}
	}
}
Beispiel #25
0
func main() {
	log.SetPrefix(fmt.Sprintf("[%d] ", syscall.Getpid()))

	var fd int
	flag.IntVar(&fd, "fd", -1, "the already-open fd to listen on")
	flag.Parse()

	server := &http.Server{Addr: ":8000"}

	var listener *zerodown.Listener
	var err error
	if fd < 0 {
		log.Println("Listening on a new fd")
		listener, err = zerodown.Listen("tcp", server.Addr)
	} else {
		log.Println("Listening to existing fd", fd)
		listener, err = zerodown.FdListen(fd)
	}
	if err != nil {
		log.Fatal(err)
	}

	mux := http.NewServeMux()
	server.Handler = mux

	mux.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, "hello world\n")
	})
	mux.HandleFunc("/sleep", func(w http.ResponseWriter, req *http.Request) {
		time.Sleep(time.Second * 10)
	})
	mux.HandleFunc("/upgrade", func(w http.ResponseWriter, req *http.Request) {
		newFd, err := listener.DupFd()
		if err != nil {
			log.Fatal(err)
		}

		cmd := exec.Command(os.Args[0], fmt.Sprintf("-fd=%d", newFd))
		cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr

		log.Println("starting cmd:", cmd.Args)
		if err := cmd.Start(); err != nil {
			log.Fatal(err)
		}

		listener.Close()
	})

	log.Println("Serving on", server.Addr)
	err = server.Serve(listener)
	if !listener.IsClosed() && err != nil {
		log.Fatal(err)
	}

	if err := listener.Wait(time.Second * 10); err != nil {
		log.Println("wait error:", err)
	} else {
		log.Println("quit")
	}
}
Beispiel #26
0
func init() {
	switch path, _ := syscall.Getenv("GOCOVOUT"); path {
	case "":
		// No tracing
	case "-":
		Default.Tracer = fdwriter(syscall.Stdout)
	default:
		// Add the process ID to the filename.
		// TODO handle PID reuse by checking if file exists.
		path += "." + itoa(syscall.Getpid())

		mode := syscall.O_WRONLY | syscall.O_CREAT | syscall.O_TRUNC
		fd, err := syscall.Open(path, mode, 0666)
		if err != nil {
			msg := "gocov: failed to create log file: "
			msg += err.Error() + "\n"
			write(fdwriter(syscall.Stderr), []byte(msg))
			syscall.Exit(1)
		}
		Default.Tracer = fdwriter(int(fd))
	}

	// Remove GOCOVOUT from environ, to prevent noise from child processes.
	// TODO Don't do this; append .pid to output filename.
	syscall.Setenv("GOCOVOUT", "")
}
Beispiel #27
0
func handle(sig os.Signal, pid int) todo {
	switch sig {
	case syscall.SIGTSTP:
		send(pid, syscall.SIGTSTP)
		fmt.Fprintf(noise, "[stopping]\n")
		syscall.Kill(syscall.Getpid(), syscall.SIGSTOP)
		time.Sleep(moment)
		fmt.Fprintf(noise, "[resuming]\n")
		send(pid, syscall.SIGCONT)
		return resumed
	case syscall.SIGHUP: // tty hangup (e.g. via disown)
		noise = ioutil.Discard
		os.Stdin.Close()
		os.Stdout.Close()
		os.Stderr.Close()
		send(pid, sig.(syscall.Signal))
		// Our tty is gone, so there is little left to do. We could hang
		// around proxying signals (e.g. those sent via kill). But those
		// could be just as easily sent directly to the hosted program,
		// so let's not bother.
		return done
	default:
		send(pid, sig.(syscall.Signal))
	}
	return cont
}
Beispiel #28
0
// NewEvaler creates a new Evaler.
func NewEvaler(st *store.Store, dataDir string) *Evaler {
	// Construct builtin namespace
	pid := str(strconv.Itoa(syscall.Getpid()))
	builtin := ns{
		"pid":   newInternalVariableWithType(pid),
		"ok":    newInternalVariableWithType(ok),
		"true":  newInternalVariableWithType(boolean(true)),
		"false": newInternalVariableWithType(boolean(false)),
	}
	for _, b := range builtinFns {
		builtin[fnPrefix+b.Name] = newInternalVariableWithType(b)
	}

	// Construct searchPaths
	var searchPaths []string
	if path := os.Getenv("PATH"); path != "" {
		searchPaths = strings.Split(path, ":")
	} else {
		searchPaths = []string{"/bin"}
	}

	return &Evaler{
		NewCompiler(makeCompilerScope(builtin), dataDir),
		ns{}, builtin, map[string]ns{},
		searchPaths, st,
	}
}
Beispiel #29
0
func TestReload_sighup(t *testing.T) {
	template := test.CreateTempfile([]byte("initial value"), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream := gatedio.NewByteBuffer()
	cli := NewCLI(outStream, outStream)

	command := fmt.Sprintf("consul-template -template %s:%s", template.Name(), out.Name())
	args := strings.Split(command, " ")

	go func(args []string) {
		if exit := cli.Run(args); exit != 0 {
			t.Fatalf("bad exit code: %d", exit)
		}
	}(args)
	defer cli.stop()

	// Ensure we have run at least once
	test.WaitForFileContents(out.Name(), []byte("initial value"), t)

	newValue := []byte("new value")
	ioutil.WriteFile(template.Name(), newValue, 0644)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)

	test.WaitForFileContents(out.Name(), []byte("new value"), t)
}
Beispiel #30
0
// RestoreParentDeathSignal sets the parent death signal to old.
func RestoreParentDeathSignal(old int) error {
	if old == 0 {
		return nil
	}

	current, err := system.GetParentDeathSignal()
	if err != nil {
		return fmt.Errorf("get parent death signal %s", err)
	}

	if old == current {
		return nil
	}

	if err := system.ParentDeathSignal(uintptr(old)); err != nil {
		return fmt.Errorf("set parent death signal %s", err)
	}

	// Signal self if parent is already dead. Does nothing if running in a new
	// PID namespace, as Getppid will always return 0.
	if syscall.Getppid() == 1 {
		return syscall.Kill(syscall.Getpid(), syscall.SIGKILL)
	}

	return nil
}