<commit_before>package crank

import (
	"fmt"
	"log"
	"os"
	"syscall"
	"time"
)

// Manager manages multiple process groups
type Manager struct {
	build           string
	configPath      string
	config          *ProcessConfig
	socket          *os.File
	processCount    int
	events          chan Event
	actions         chan Action
	childs          processSet
	shuttingDown    bool
	startingTracker *TimeoutTracker
	stoppingTracker *TimeoutTracker
	startingReply   *StartReply
	startingDone    chan<- error
}

func NewManager(build string, configPath string, socket *os.File) *Manager {
	config, err := loadProcessConfig(configPath)
	if err != nil {
		log.Println("Could not load config file: ", err)
	}

	manager := &Manager{
		build:           build,
		configPath:      configPath,
		config:          config,
		socket:          socket,
		events:          make(chan Event),
		actions:         make(chan Action),
		childs:          make(processSet),
		startingTracker: NewTimeoutTracker(),
		stoppingTracker: NewTimeoutTracker(),
	}
	return manager
}

// Run starts the event loop for the manager process
func (self *Manager) Run() {
	if len(self.config.Command) == 0 {
		self.log("Ignoring process start, command is missing")
	} else {
		err := self.startProcess(self.config)
		if err != nil {
			self.log("Failed to start the process: %s", err)
			return
		}
	}

	go self.startingTracker.Run()
	go self.stoppingTracker.Run()

	for {
		select {
		// actions
		case a := <-self.actions:
			switch action := a.(type) {
			case ShutdownAction:
				if self.shuttingDown {
					self.log("Already shutting down")
					continue
				}
				self.log("Shutting down")
				self.shuttingDown = true
				self.childs.each(func(p *Process) {
					self.stopProcess(p)
				})
				if self.childs.len() == 0 {
					goto exit
				}
			case *StartAction:
				query := action.query
				//reply := action.reply -- not used
<commit_msg>Close the bound socket early in the crank shutdown process. Fixes #23<commit_after>package crank

import (
	"fmt"
	"log"
	"os"
	"syscall"
	"time"
)

// Manager manages multiple process groups
type Manager struct {
	build           string
	configPath      string
	config          *ProcessConfig
	socket          *os.File
	processCount    int
	events          chan Event
	actions         chan Action
	childs          processSet
	shuttingDown    bool
	startingTracker *TimeoutTracker
	stoppingTracker *TimeoutTracker
	startingReply   *StartReply
	startingDone    chan<- error
}

func NewManager(build string, configPath string, socket *os.File) *Manager {
	config, err := loadProcessConfig(configPath)
	if err != nil {
		log.Println("Could not load config file: ", err)
	}

	manager := &Manager{
		build:           build,
		configPath:      configPath,
		config:          config,
		socket:          socket,
		events:          make(chan Event),
		actions:         make(chan Action),
		childs:          make(processSet),
		startingTracker: NewTimeoutTracker(),
		stoppingTracker: NewTimeoutTracker(),
	}
	return manager
}

// Run starts the event loop for the manager process
func (self *Manager) Run() {
	if len(self.config.Command) == 0 {
		self.log("Ignoring process start, command is missing")
	} else {
		err := self.startProcess(self.config)
		if err != nil {
			self.log("Failed to start the process: %s", err)
			return
		}
	}

	go self.startingTracker.Run()
	go self.stoppingTracker.Run()

	for {
		select {
		// actions
		case a := <-self.actions:
			switch action := a.(type) {
			case ShutdownAction:
				if self.shuttingDown {
					self.log("Already shutting down")
					continue
				}
				self.log("Shutting down")
				self.shuttingDown = true

				// Makes the socket unavailable as soon as possible
				self.socket.Close()

				self.childs.each(func(p *Process) {
					self.stopProcess(p)
				})
				if self.childs.len() == 0 {
					goto exit
				}
			case *StartAction:
				query := action.query
				//reply := action.reply -- not used

{'fraction_non_alphanumeric': 0.10257705912076806, 'fraction_numerical': 0.0015159171298635675, 'mean_word_length': 2.6691380908248377, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, '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': '1638221', 'n_tokens_mistral': 1407, 'n_tokens_neox': 1197, 'n_words': 352}