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