blob: 287d11bd8c29f6a0bc46225183a669b06c03275e [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package poll
import (
// asyncIO implements asynchronous cancelable I/O.
// An asyncIO represents a single asynchronous Read or Write
// operation. The result is returned on the result channel.
// The undergoing I/O system call can either complete or be
// interrupted by a note.
type asyncIO struct {
res chan result
// mu guards the pid field.
mu sync.Mutex
// pid holds the process id of
// the process running the IO operation.
pid int
// result is the return value of a Read or Write operation.
type result struct {
n int
err error
// newAsyncIO returns a new asyncIO that performs an I/O
// operation by calling fn, which must do one and only one
// interruptible system call.
func newAsyncIO(fn func([]byte) (int, error), b []byte) *asyncIO {
aio := &asyncIO{
res: make(chan result, 0),
go func() {
// Lock the current goroutine to its process
// and store the pid in io so that Cancel can
// interrupt it. We ignore the "hangup" signal,
// so the signal does not take down the entire
// Go runtime.
runtime_ignoreHangup() = syscall.Getpid()
n, err := fn(b) = -1
aio.res <- result{n, err}
return aio
// Cancel interrupts the I/O operation, causing
// the Wait function to return.
func (aio *asyncIO) Cancel() {
if == -1 {
f, e := syscall.Open("/proc/"+itoa("/note", syscall.O_WRONLY)
if e != nil {
syscall.Write(f, []byte("hangup"))
// Wait for the I/O operation to complete.
func (aio *asyncIO) Wait() (int, error) {
res := <-aio.res
return res.n, res.err
// The following functions, provided by the runtime, are used to
// ignore and unignore the "hangup" signal received by the process.
func runtime_ignoreHangup()
func runtime_unignoreHangup()