Spec-Zone.ru › Go

Пакет signal

  • import "os/signal"
  • Обзор
  • Индекс
  • Примеры

Обзор

Пакет signal реализует доступ к входящим сигналам.

Сигналы в основном используются в системах Unix-подобных. Для использования этого пакета в Windows и Plan 9 см. ниже.

Типы сигналов

Сигналы SIGKILL и SIGSTOP не могут быть перехвачены программой и поэтому не могут быть затронуты этим пакетом.

Синхронные сигналы — это сигналы, которые генерируются ошибками в выполнении программы: SIGBUS, SIGFPE и SIGSEGV. Они считаются синхронными только тогда, когда вызваны выполнением программы, а не когда отправлены с помощью os.Process.Kill или программы kill или каким-либо подобным механизмом. В общем случае, за исключением случаев, обсуждаемых ниже, программы Go превратят синхронный сигнал в панику во время выполнения.

Остальные сигналы являются асинхронными сигналами. Они не вызываются ошибками программы, а вместо этого отправляются ядром или другой программой.

Из асинхронных сигналов сигнал SIGHUP отправляется, когда программа теряет свой управляющий терминал. Сигнал SIGINT отправляется, когда пользователь на управляющем терминале нажимает символ прерывания, по умолчанию это ^C (Control-C). Сигнал SIGQUIT отправляется, когда пользователь на управляющем терминале нажимает символ выхода, по умолчанию это ^\ (Control-Backslash). В общем случае вы можете заставить программу просто выйти, нажав ^C, и вы можете заставить её выйти со дампом стека, нажав ^\.

Поведение сигналов по умолчанию в программах Go

По умолчанию синхронный сигнал преобразуется в панику во время выполнения. Сигналы SIGHUP, SIGINT или SIGTERM вызывают выход программы. Сигналы SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGSTKFLT, SIGEMT или SIGSYS вызывают выход программы с дампом стека. Сигналы SIGTSTP, SIGTTIN или SIGTTOU получают системное поведение по умолчанию (эти сигналы используются оболочкой для управления задачами). Сигнал SIGPROF обрабатывается непосредственно средой выполнения Go для реализации runtime.CPUProfile. Другие сигналы будут перехвачены, но никаких действий не будет выполнено.

Если программа Go запущена с игнорированием SIGHUP или SIGINT (обработчик сигнала установлен на SIG_IGN), они останутся проигнорированными.

Если программа Go запущена с непустым маской сигналов, это, как правило, будет учтено. Однако некоторые сигналы явно разблокированы: синхронные сигналы, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF и, в Linux, сигналы 32 (SIGCANCEL) и 33 (SIGSETXID) (SIGCANCEL и SIGSETXID используются внутри glibc). Подпроцессы, запущенные с помощью os.Exec, или os/exec, унаследуют изменённую маску сигналов.

Изменение поведения сигналов в программах Go

Функции в этом пакете позволяют программе изменить способ обработки сигналов в программах Go.

Notify отключает поведение по умолчанию для заданного набора асинхронных сигналов и вместо этого доставляет их по одному или нескольким зарегистрированным каналам. В частности, это относится к сигналам SIGHUP, SIGINT, SIGQUIT, SIGABRT и SIGTERM. Это также относится к сигналам управления задачами SIGTSTP, SIGTTIN и SIGTTOU, в этом случае не происходит системное поведение по умолчанию. Это также относится к некоторым сигналам, которые в противном случае не вызывают никаких действий: SIGUSR1, SIGUSR2, SIGPIPE, SIGALRM, SIGCHLD, SIGCONT, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGWINCH, SIGIO, SIGPWR, SIGINFO, SIGTHR, SIGWAITING, SIGLWP, SIGFREEZE, SIGTHAW, SIGLOST, SIGXRES, SIGJVM1, SIGJVM2 и любым сигналам реального времени, используемым в системе. Обратите внимание, что не все эти сигналы доступны во всех системах.

Если программа была запущена с игнорированием SIGHUP или SIGINT, и Notify вызывается для любого из этих сигналов, для него будет установлен обработчик сигнала, и он больше не будет игнорироваться. Если позже вызовется Reset или Ignore для этого сигнала, или Stop вызывается для всех каналов, переданных в Notify для этого сигнала, сигнал снова будет игнорироваться. Reset восстановит системное поведение по умолчанию для сигнала, в то время как Ignore заставит систему полностью игнорировать сигнал.

Если программа запускается с непустой маской сигналов, некоторые сигналы будут явно разблокированы, как описано выше. Если Notify вызывается для заблокированного сигнала, он будет разблокирован. Если позже вызывается Reset для этого сигнала или Stop вызывается для всех каналов, переданных в Notify для этого сигнала, сигнал снова будет заблокирован.

SIGPIPE

Когда программа Go записывает в повреждённую трубу, ядро генерирует сигнал SIGPIPE.

Если программа не вызвала Notify для получения сигналов SIGPIPE, поведение зависит от номера дескриптора файла. Запись в повреждённую трубу по дескрипторам файлов 1 или 2 (стандартный вывод или стандартная ошибка) приведёт к выходу программы с сигналом SIGPIPE. Запись в повреждённую трубу по другому дескриптору файла не повлияет на сигнал SIGPIPE, и запись завершится ошибкой EPIPE.

Если программа вызвала Notify для получения сигналов SIGPIPE, номер дескриптора файла не имеет значения. Сигнал SIGPIPE будет передан в канал Notify, а запись завершится ошибкой EPIPE.

Это означает, что по умолчанию командные программы будут вести себя как типичные командные программы Unix, в то время как другие программы не будут аварийно завершаться с SIGPIPE при записи в закрытое сетевое соединение.

Программы Go, использующие cgo или SWIG

В программе Go, включающей код, не написанный на Go (обычно C/C++ код, к которому осуществляется доступ с помощью cgo или SWIG), код инициализации Go обычно выполняется первым. Он настраивает обработчики сигналов так, как ожидается от среды выполнения Go, прежде чем выполняется код инициализации не-Go. Если код инициализации не-Go хочет установить свои собственные обработчики сигналов, он должен предпринять определённые шаги, чтобы Go работал корректно. В этом разделе описаны эти шаги и общее влияние изменений настроек обработчиков сигналов кодом не-Go на программы Go. В редких случаях код не-Go может выполняться до кода Go, в этом случае также применяется следующий раздел.

Если код не-Go, вызываемый программой Go, не изменяет обработчики или маски сигналов, поведение такое же, как и для чистой программы Go.

Если код не-Go устанавливает обработчики сигналов, он должен использовать флаг SA_ONSTACK с sigaction. Несоблюдение этого может привести к аварийному завершению программы, если сигнал получен. Программы Go обычно работают с ограниченным стеком и, следовательно, настраивают альтернативный стек сигналов.

Если код не-Go устанавливает обработчик сигналов для любого из синхронных сигналов (SIGBUS, SIGFPE, SIGSEGV), то он должен сохранить существующий обработчик сигналов Go. Если эти сигналы возникают во время выполнения кода Go, он должен вызвать обработчик сигналов Go (это можно определить, посмотрев на PC, переданный обработчику сигнала). В противном случае некоторые ошибки Go во время выполнения не произойдут как ожидается.

Если код не-Go устанавливает обработчик сигналов для любого из асинхронных сигналов, он может вызвать обработчик сигналов Go или нет, по своему усмотрению. Естественно, если он не вызывает обработчик сигналов Go, поведение Go, описанное выше, не произойдёт. Это может быть проблемой с сигналом SIGPROF, в частности.

Код не-Go не должен изменять маску сигналов на нитях, созданных средой выполнения Go. Если код не-Go запускает новые потоки, эти потоки могут устанавливать маску сигналов по своему усмотрению.

Если код не-Go запускает новую нить, изменяет маску сигналов и затем вызывает функцию Go в этой нити, среда выполнения Go автоматически разблокирует определённые сигналы: синхронные сигналы, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF, SIGCANCEL и SIGSETXID. Когда функция Go возвращается, маска сигналов кода не-Go восстанавливается.

Если обработчик сигнала Go вызывается в потоке не-Go, не выполняющем код Go, обработчик, как правило, пересылает сигнал коду не-Go, как указано ниже. Если сигнал — SIGPROF, обработчик Go ничего не делает. В противном случае обработчик Go удаляет себя, разблокирует сигнал и снова генерирует его, чтобы вызвать любой обработчик не-Go или системный обработчик по умолчанию. Если программа не выходит, обработчик Go затем переустанавливает себя и продолжает выполнение программы.

Если получен сигнал SIGPIPE, программа Go вызовет специальную обработку, описанную выше, если SIGPIPE получен в потоке Go. Если SIGPIPE получен в потоке не-Go, сигнал будет передан обработчику не-Go, если он есть; если его нет, системный обработчик по умолчанию приведёт к завершению программы.

Программы не-Go, вызывающие код Go

Когда код Go создаётся с такими параметрами, как -buildmode=c-shared, он будет выполняться как часть существующей программы не-Go. Код не-Go может уже установить обработчики сигналов, когда запускается код Go (это также может произойти в необычных случаях при использовании cgo или SWIG; в этом случае обсуждение здесь применимо). Для -buildmode=c-archive среда выполнения Go инициализирует сигналы во время глобального времени конструктора. Для -buildmode=c-shared среда выполнения Go инициализирует сигналы при загрузке разделяемой библиотеки.

Если среда выполнения Go видит существующий обработчик сигнала для сигналов SIGCANCEL или SIGSETXID (которые используются только в Linux), она установит флаг SA_ONSTACK и иначе сохранит обработчик сигнала.

Для синхронных сигналов и SIGPIPE среда выполнения Go установит обработчик сигнала. Она сохранит любой существующий обработчик сигнала. Если синхронный сигнал поступает во время выполнения кода не-Go, среда выполнения Go вызовет существующий обработчик сигнала вместо обработчика сигнала Go.

Код Go, созданный с -buildmode=c-archive или -buildmode=c-shared, по умолчанию не устанавливает другие обработчики сигналов. Если существует существующий обработчик сигнала, среда выполнения Go установит флаг SA_ONSTACK и иначе сохранит обработчик сигнала. Если Notify вызывается для асинхронного сигнала, для этого сигнала будет установлен обработчик сигнала Go. Если позже вызывается Reset для этого сигнала, исходная обработка для этого сигнала будет переустановлена, восстанавливая обработчик сигнала не-Go, если таковой имеется.

Код Go, созданный без -buildmode=c-archive или -buildmode=c-shared, установит обработчик сигнала для перечисленных выше асинхронных сигналов и сохранит любой существующий обработчик сигнала. Если сигнал отправлен потоку не-Go, он будет действовать, как описано выше, за исключением того, что если существует существующий обработчик сигнала не-Go, этот обработчик будет установлен перед возбуждением сигнала.

Windows

В Windows ^C (Control-C) или ^BREAK (Control-Break) обычно приводят к выходу программы. Если вызвана Notify для os.Interrupt, ^C или ^BREAK отправят os.Interrupt в канал, и программа не выйдет. Если вызвана Reset или Stop для всех каналов, переданных в Notify, будет восстановлено поведение по умолчанию.

Кроме того, если вызвана Notify, и Windows отправит CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT или CTRL_SHUTDOWN_EVENT процессу, Notify вернёт syscall.SIGTERM. В отличие от Control-C и Control-Break, Notify не изменяет поведение процесса при получении CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT или CTRL_SHUTDOWN_EVENT — процесс по-прежнему будет завершён, если не выйдет самостоятельно. Но получение syscall.SIGTERM даст процессу возможность завершить работу, прежде чем он будет закрыт.

Plan 9

В Plan 9 сигналы имеют тип syscall.Note, который является строкой. Вызов Notify со значением syscall.Note приведет к отправке этого значения по каналу, когда эта строка будет опубликована как заметка.

Индекс

  • func Ignore(sig ...os.Signal)
  • func Ignored(sig os.Signal) bool
  • func Notify(c chan<- os.Signal, sig ...os.Signal)
  • func NotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)
  • func Reset(sig ...os.Signal)
  • func Stop(c chan<- os.Signal)

Примеры

Notify
NotifyContext
Notify (ВсеСигналы)

Файлы пакета

doc.gosignal.gosignal_unix.go

func Ignore 1.5

func Ignore(sig ...os.Signal)

Ignore игнорирует указанные сигналы. Если они получены программой, ничего не произойдёт. Ignore отменяет действие любых предыдущих вызовов Notify для указанных сигналов. Если сигналы не указаны, все входящие сигналы будут игнорироваться.

func Ignored 1.11

func Ignored(sig os.Signal) bool

Ignored сообщает, игнорируется ли в данный момент сигнал sig.

func Notify

func Notify(c chan<- os.Signal, sig ...os.Signal)

Notify заставляет пакет signal пересылать входящие сигналы в c. Если сигналы не указаны, все входящие сигналы будут пересылаться в c. В противном случае будут пересылаться только указанные сигналы.

Пакет signal не будет блокировать отправку в c: вызывающая сторона должна гарантировать, что c имеет достаточный буфер, чтобы успевать за ожидаемой скоростью сигнализации. Для канала, используемого для уведомления только об одном значении сигнала, буфера размером 1 достаточно.

Разрешается вызывать Notify несколько раз с одним и тем же каналом: каждый вызов расширяет набор сигналов, отправляемых в этот канал. Единственный способ удалить сигналы из набора — вызвать Stop.

Разрешается вызывать Notify несколько раз с различными каналами и одними и теми же сигналами: каждый канал получает копии входящих сигналов независимо.

Пример

Код:

// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)

// Block until a signal is received.
s := <-c
fmt.Println("Got signal:", s)

Пример (ВсеСигналы)

Код:

// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)

// Passing no signals to Notify means that
// all signals will be sent to the channel.
signal.Notify(c)

// Block until any signal is received.
s := <-c
fmt.Println("Got signal:", s)

func NotifyContext 1.16

func NotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)

NotifyContext возвращает копию родительского контекста, который отмечается как завершённый (его канал Done закрывается), когда приходит один из перечисленных сигналов, когда вызывается возвращённая функция stop или когда закрывается канал Done родительского контекста, в зависимости от того, что произойдёт раньше.

Функция stop отменяет обработку сигнала, которая, как и signal.Reset, может восстановить поведение по умолчанию для данного сигнала. Например, поведение программы Go по умолчанию при получении os.Interrupt — выход. Вызов NotifyContext(parent, os.Interrupt) изменит поведение на отмену возвращаемого контекста. Будущие прерывания не будут вызывать поведение по умолчанию (выход) до тех пор, пока не будет вызвана возвращённая функция stop.

Функция stop освобождает ресурсы, связанные с ней, поэтому код должен вызвать stop как только завершатся операции, выполняющиеся в этом контексте, и больше не нужно перенаправлять сигналы в контекст.

Пример

В этом примере передаётся контекст с сигналом, чтобы сообщить блокирующей функции, что ей следует прекратить свою работу после получения сигнала.

Код:

package signal_test

import (
    "context"
    "fmt"
    "log"
    "os"
    "os/signal"
)

var neverReady = make(chan struct{}) // never closed

// This example passes a context with a signal to tell a blocking function that
// it should abandon its work after a signal is received.
func ExampleNotifyContext() {
    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    defer stop()

    p, err := os.FindProcess(os.Getpid())
    if err != nil {
        log.Fatal(err)
    }

    // On a Unix-like system, pressing Ctrl+C on a keyboard sends a
    // SIGINT signal to the process of the program in execution.
    //
    // This example simulates that by sending a SIGINT signal to itself.
    if err := p.Signal(os.Interrupt); err != nil {
        log.Fatal(err)
    }

    select {
    case <-neverReady:
        fmt.Println("ready")
    case <-ctx.Done():
        fmt.Println(ctx.Err()) // prints "context canceled"
        stop()                 // stop receiving signal notifications as soon as possible.
    }

    // Output:
    // context canceled
}

func Reset 1.5

func Reset(sig ...os.Signal)

Reset отменяет действие любых предыдущих вызовов Notify для указанных сигналов. Если сигналы не указаны, все обработчики сигналов будут сброшены.

func Stop 1.1

func Stop(c chan<- os.Signal)

Stop заставляет пакет signal прекратить пересылку входящих сигналов в c. Он отменяет действие всех предыдущих вызовов Notify с использованием c. После возврата Stop гарантируется, что c больше не получит сигналов.

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/os/signal/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API