/usr/share/gocode/src/github.com/cloudfoundry/gosigar/psnotify/psnotify.go is in golang-github-cloudfoundry-gosigar-dev 0.0~git20150402.27.3ed7c74-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | // Copyright (c) 2012 VMware, Inc.
package psnotify
import (
"errors"
"fmt"
)
type ProcEventFork struct {
ParentPid int // Pid of the process that called fork()
ChildPid int // Child process pid created by fork()
}
type ProcEventExec struct {
Pid int // Pid of the process that called exec()
}
type ProcEventExit struct {
Pid int // Pid of the process that called exit()
}
type watch struct {
flags uint32 // Saved value of Watch() flags param
}
type eventListener interface {
close() error // Watch.Close() closes the OS specific listener
}
type Watcher struct {
listener eventListener // OS specifics (kqueue or netlink)
watches map[int]*watch // Map of watched process ids
Error chan error // Errors are sent on this channel
Fork chan *ProcEventFork // Fork events are sent on this channel
Exec chan *ProcEventExec // Exec events are sent on this channel
Exit chan *ProcEventExit // Exit events are sent on this channel
done chan bool // Used to stop the readEvents() goroutine
isClosed bool // Set to true when Close() is first called
}
// Initialize event listener and channels
func NewWatcher() (*Watcher, error) {
listener, err := createListener()
if err != nil {
return nil, err
}
w := &Watcher{
listener: listener,
watches: make(map[int]*watch),
Fork: make(chan *ProcEventFork),
Exec: make(chan *ProcEventExec),
Exit: make(chan *ProcEventExit),
Error: make(chan error),
done: make(chan bool, 1),
}
go w.readEvents()
return w, nil
}
// Close event channels when done message is received
func (w *Watcher) finish() {
close(w.Fork)
close(w.Exec)
close(w.Exit)
close(w.Error)
}
// Closes the OS specific event listener,
// removes all watches and closes all event channels.
func (w *Watcher) Close() error {
if w.isClosed {
return nil
}
w.isClosed = true
for pid := range w.watches {
w.RemoveWatch(pid)
}
w.done <- true
w.listener.close()
return nil
}
// Add pid to the watched process set.
// The flags param is a bitmask of process events to capture,
// must be one or more of: PROC_EVENT_FORK, PROC_EVENT_EXEC, PROC_EVENT_EXIT
func (w *Watcher) Watch(pid int, flags uint32) error {
if w.isClosed {
return errors.New("psnotify watcher is closed")
}
watchEntry, found := w.watches[pid]
if found {
watchEntry.flags |= flags
} else {
if err := w.register(pid, flags); err != nil {
return err
}
w.watches[pid] = &watch{flags: flags}
}
return nil
}
// Remove pid from the watched process set.
func (w *Watcher) RemoveWatch(pid int) error {
_, ok := w.watches[pid]
if !ok {
msg := fmt.Sprintf("watch for pid=%d does not exist", pid)
return errors.New(msg)
}
delete(w.watches, pid)
return w.unregister(pid)
}
// Internal helper to check if there is a message on the "done" channel.
// The "done" message is sent by the Close() method; when received here,
// the Watcher.finish method is called to close all channels and return
// true - in which case the caller should break from the readEvents loop.
func (w *Watcher) isDone() bool {
var done bool
select {
case done = <-w.done:
w.finish()
default:
}
return done
}
|