<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"os"
	"os/exec"
	"syscall"
	"time"

	. "github.com/google/syzkaller/pkg/log"
)

// ManagerCmd encapsulates a single instance of syz-manager process.
// It automatically restarts syz-manager if it exits unexpectedly,
// and supports graceful shutdown via SIGINT.
type ManagerCmd struct {
	name    string
	log     string
	bin     string
	args    []string
	closing chan bool
}

// NewManagerCmd starts new syz-manager process.
// name - name for logging.
// log - manager log file with stdout/stderr.
// bin/args - process binary/args.
func NewManagerCmd(name, log, bin string, args ...string) *ManagerCmd {
	mc := &ManagerCmd{
		name:    name,
		log:     log,
		bin:     bin,
		args:    args,
		closing: make(chan bool),
	}
	go mc.loop()
	return mc
}

// Close gracefully shutdowns the process and waits for its termination.
func (mc *ManagerCmd) Close() {
	mc.closing <- true
	<-mc.closing
}

func (mc *ManagerCmd) loop() {
	const (
		restartPeriod    = time.Minute // don't restart crashing manager more frequently than that
		interruptTimeout = time.Minute // give manager that much time to react to SIGINT
	)
	var (
		cmd         *exec.Cmd
		started     time.Time
		interrupted time.Time
		stopped     = make(chan error, 1)
		closing     = mc.closing
		ticker1     = time.NewTicker(restartPeriod)
		ticker2     = time.NewTicker(interruptTimeout)
	)
	defer func() {
		ticker1.Stop()
		ticker2.Stop()
	}()
	for closing != nil || cmd != nil {
		if cmd == nil {
			// cmd is not running
			// don't restart too frequently (in case it instantly exits with an error)
			if time.Since(started) > restartPeriod {
				started = time.Now()
				logfile, err := os.Create(mc.log)
				if err != nil {
					Logf(1, "%v: failed to create manager log: %v", mc.name, err)
				} else {
					cmd = exec.Command(mc.bin, mc.args...)
					cmd.Stdout = logfile
					cmd.Stderr = logfile
					err := cmd.Start()
					logfile.Close()
					if err != nil {
						Logf(1, "%v: failed to start manager: %v", mc.name, err)
						cmd = nil
					} else {<commit_msg>syz-ci: save previous manager log<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"os"
	"os/exec"
	"syscall"
	"time"

	. "github.com/google/syzkaller/pkg/log"
)

// ManagerCmd encapsulates a single instance of syz-manager process.
// It automatically restarts syz-manager if it exits unexpectedly,
// and supports graceful shutdown via SIGINT.
type ManagerCmd struct {
	name    string
	log     string
	bin     string
	args    []string
	closing chan bool
}

// NewManagerCmd starts new syz-manager process.
// name - name for logging.
// log - manager log file with stdout/stderr.
// bin/args - process binary/args.
func NewManagerCmd(name, log, bin string, args ...string) *ManagerCmd {
	mc := &ManagerCmd{
		name:    name,
		log:     log,
		bin:     bin,
		args:    args,
		closing: make(chan bool),
	}
	go mc.loop()
	return mc
}

// Close gracefully shutdowns the process and waits for its termination.
func (mc *ManagerCmd) Close() {
	mc.closing <- true
	<-mc.closing
}

func (mc *ManagerCmd) loop() {
	const (
		restartPeriod    = time.Minute // don't restart crashing manager more frequently than that
		interruptTimeout = time.Minute // give manager that much time to react to SIGINT
	)
	var (
		cmd         *exec.Cmd
		started     time.Time
		interrupted time.Time
		stopped     = make(chan error, 1)
		closing     = mc.closing
		ticker1     = time.NewTicker(restartPeriod)
		ticker2     = time.NewTicker(interruptTimeout)
	)
	defer func() {
		ticker1.Stop()
		ticker2.Stop()
	}()
	for closing != nil || cmd != nil {
		if cmd == nil {
			// cmd is not running
			// don't restart too frequently (in case it instantly exits with an error)
			if time.Since(started) > restartPeriod {
				started = time.Now()
				os.Rename(mc.log, mc.log+".old")
				logfile, err := os.Create(mc.log)
				if err != nil {
					Logf(0, "%v: failed to create manager log: %v", mc.name, err)
				} else {
					cmd = exec.Command(mc.bin, mc.args...)
					cmd.Stdout = logfile
					cmd.Stderr = logfile
					err := cmd.Start()
					logfile.Close()
					if err != nil {
						Logf(0, "%v: failed to start manager: %v", mc.name, err)
						cmd = nil
					} else {
{'fraction_non_alphanumeric': 0.11240908089045624, 'fraction_numerical': 0.005289839100727353, 'mean_word_length': 2.7257799671592773, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3702057', 'n_tokens_mistral': 1691, 'n_tokens_neox': 1471, 'n_words': 506}