kana-desu
@kana-desu
Golang, Clojure, Elixir, Ruby

Как полностью убить дочерний процесс?

Имею простейший код, который просто в течении 5/3 секунды выводит числа.
func main() {
	flag.Parse()
	for i := 0; i < 5; i++ {
		fmt.Println(flag.Arg(0), i)
		time.Sleep(time.Second / 3)
	}
}


В другой программе я в цикле запускаю "go run first.go %{i}", где i - просто индекс цикла и жду завершения процесса. Но через секунду после запуска я убиваю процесс (cmd.Process.Kill()). cmd.Wait() разблокировывается, процесс считается убитым, цикл начинается сначала. Вот только числа продолжают выводиться до конца работы программы (5/3 секунды). Как такое возможно, что процесс вроде убитый, но при этом продолжает работать?

Вот весь код

Есть подозрение, что я убиваю go, а вот дочерний процесс (бинарник, скомпилированный go) отходит к init, потом заканчивает свое действие и умирает. Тогда нужно или собирать самому и запускать бинарник, или узнать, как убить go вместе с запущенным бинарником.
  • Вопрос задан
  • 532 просмотра
Пригласить эксперта
Ответы на вопрос 2
@mantyr
Пишу много Golang кода с удовольствием:)
go run имеет особенности, к примеру вы можете запустить его в консоли и забыть - от консоли он спокойно отвяжется. Тут у вас аналогичная ситуация. Если вы хотите запускать некий код в "дочернем" процессе то делайте это явно:
1. через fork() - что не желательно
2. через go-рутины
3. ...
Но, судя по всему, вы пытаетесь скрестить Golang приложение с приложением на другом языке (иначе откуда такие заморочки). В таком случае вам нужно:
1. научить приложение (first.go) понимать сигналы операционной системы, для этого изучите os.Signal и syscall.SIGKILL (вообще почитайте на тему какие сигналы надо обрабатывать при завершении приложения) и завершайте приложение правильно в нужный момент
2. всё таки скомпилируйте вначале в бинарник, go install first.go и используйте уже именно его...

Ну и напоследок - не надо так расходовать ресурсы - запускать N раз другую программу что бы просто посчитать несколько однотипных цифр. Сформируйте программу более ёмко, отправьте ей кучу данных и получите от неё другую кучу результатов разом. Или сделайте многопоточный сервис который принимает запросы и выдаёт ответы.
Ответ написан
Albibek
@Albibek
Вопросы есть? А если найду?
Можно попросить ядро посылать дочернему процессу SIGHUP, когда умирает родительский процесс.
https://stackoverflow.com/questions/284325/how-to-...

Но в GO без C-кода этого, похоже, пока что не сделать.
Вот обсуждение: https://groups.google.com/forum/#!topic/golang-dev...

Если родительский процесс "умирает" контролируемо, отправьте сигнал TERM (в крайнем случае, KILL) всем дочерним процессам самостоятельно. Так будет лучше всего. Если неконтролируемо, разбирайтесь с родительским.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы