...

Source file src/internal/poll/fd_io_plan9.go

     1	// Copyright 2016 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package poll
     6	
     7	import (
     8		"runtime"
     9		"sync"
    10		"syscall"
    11	)
    12	
    13	// asyncIO implements asynchronous cancelable I/O.
    14	// An asyncIO represents a single asynchronous Read or Write
    15	// operation. The result is returned on the result channel.
    16	// The undergoing I/O system call can either complete or be
    17	// interrupted by a note.
    18	type asyncIO struct {
    19		res chan result
    20	
    21		// mu guards the pid field.
    22		mu sync.Mutex
    23	
    24		// pid holds the process id of
    25		// the process running the IO operation.
    26		pid int
    27	}
    28	
    29	// result is the return value of a Read or Write operation.
    30	type result struct {
    31		n   int
    32		err error
    33	}
    34	
    35	// newAsyncIO returns a new asyncIO that performs an I/O
    36	// operation by calling fn, which must do one and only one
    37	// interruptible system call.
    38	func newAsyncIO(fn func([]byte) (int, error), b []byte) *asyncIO {
    39		aio := &asyncIO{
    40			res: make(chan result, 0),
    41		}
    42		aio.mu.Lock()
    43		go func() {
    44			// Lock the current goroutine to its process
    45			// and store the pid in io so that Cancel can
    46			// interrupt it. We ignore the "hangup" signal,
    47			// so the signal does not take down the entire
    48			// Go runtime.
    49			runtime.LockOSThread()
    50			runtime_ignoreHangup()
    51			aio.pid = syscall.Getpid()
    52			aio.mu.Unlock()
    53	
    54			n, err := fn(b)
    55	
    56			aio.mu.Lock()
    57			aio.pid = -1
    58			runtime_unignoreHangup()
    59			aio.mu.Unlock()
    60	
    61			aio.res <- result{n, err}
    62		}()
    63		return aio
    64	}
    65	
    66	// Cancel interrupts the I/O operation, causing
    67	// the Wait function to return.
    68	func (aio *asyncIO) Cancel() {
    69		aio.mu.Lock()
    70		defer aio.mu.Unlock()
    71		if aio.pid == -1 {
    72			return
    73		}
    74		f, e := syscall.Open("/proc/"+itoa(aio.pid)+"/note", syscall.O_WRONLY)
    75		if e != nil {
    76			return
    77		}
    78		syscall.Write(f, []byte("hangup"))
    79		syscall.Close(f)
    80	}
    81	
    82	// Wait for the I/O operation to complete.
    83	func (aio *asyncIO) Wait() (int, error) {
    84		res := <-aio.res
    85		return res.n, res.err
    86	}
    87	
    88	// The following functions, provided by the runtime, are used to
    89	// ignore and unignore the "hangup" signal received by the process.
    90	func runtime_ignoreHangup()
    91	func runtime_unignoreHangup()
    92	

View as plain text