package door import ( "log" "syscall" "time" ) var ReaderInterval = time.Duration(200) * time.Millisecond var ReaderTimeval syscall.Timeval = syscall.Timeval{0, 200} func clearAll(fdSetPtr *syscall.FdSet) { for index := range (*fdSetPtr).Bits { (*fdSetPtr).Bits[index] = 0 } } func set(fdSetPtr *syscall.FdSet, fd int) { (*fdSetPtr).Bits[fd/64] |= 1 << uint64(fd%64) } func Reader(d *Door) { // I need non-blocking reads here. // I'm not really using either of these things. // d.readerFile = os.NewFile(uintptr(d.READFD), "Door FD") // d.runereader = bufio.NewReaderSize(d.readerFile, 1) defer func() { log.Printf("~Reader\n") if d.ReaderCanClose { d.wg.Done() } }() defer func() { if err := recover(); err != nil { log.Printf("Reader: %#v\n", err) } }() var fdset syscall.FdSet for { clearAll(&fdset) set(&fdset, d.READFD) v, err := syscall.Select(d.READFD+1, &fdset, nil, nil, &ReaderTimeval) if err == syscall.EINTR { continue } // log.Printf("Select: %#v / %#v\n", v, err) if v == -1 { log.Printf("Reader ERR: %#v\n", err) d.readerMutex.Lock() if !d.ReaderClosed { d.ReaderClosed = true close(d.readerChannel) } return } if v == 0 { // timeout continue } // d.readerFile.SetReadDeadline(time.Now().Add(ReaderInterval)) // not on a os.File you won't. :P // r, _, err := d.runereader.ReadRune() buffer := make([]byte, 1) r, err := syscall.Read(d.READFD, buffer) if r == -1 { log.Println("Read -1 (closed)") d.readerMutex.Lock() defer d.readerMutex.Unlock() if !d.ReaderClosed { d.ReaderClosed = true d.Disconnected = true close(d.readerChannel) } return } if r != 1 { log.Printf("Select said ready, but: %#v %#v\n", r, err) d.readerMutex.Lock() defer d.readerMutex.Unlock() if !d.ReaderClosed { d.ReaderClosed = true d.Disconnected = true close(d.readerChannel) } return } if DEBUG_INPUT { log.Printf("Reader (byte): %#v\n", buffer[0]) } d.readerChannel <- rune(buffer[0]) /* if r == unicode.ReplacementChar { _ = d.runereader.UnreadRune() b, _ := d.runereader.ReadByte() if DEBUG_INPUT { log.Printf("Reader (byte): %#v\n", b) } d.readerChannel <- rune(b) continue } if err == nil { if DEBUG_INPUT { log.Printf("Reader (rune): %#v\n", r) } d.readerChannel <- r continue } */ // I'm not sure I care what the error is we're getting here... /* if e, ok := err.(net.Error); ok && e.Timeout() { } else { } */ /* log.Printf("Reader ERR: %#v\n", err) d.ReaderClosed = true close(d.readerChannel) return */ } } /* func Reader(handle int, readerChannel *chan byte) { // I don't need the select anymore. Let the read block. defer func() { if err := recover(); err != nil { log.Printf("Reader: %#v\n", err) } }() buffer := make([]byte, 1) for { // blocking read in go routine // why doesn't this end when I close the handle? read, err := syscall.Read(handle, buffer) if err != nil { log.Printf("Reader ERR: %#v\n", err) close(*readerChannel) break } if read == 1 { *readerChannel <- buffer[0] } else { log.Printf("READ FAILED %d\n", read) close(*readerChannel) break } } } // This doesn't work. Closing the handle does not unblock the syscall.Read above. func CloseReader(handle int) { defer func() { if err := recover(); err != nil { log.Printf("CloseReader: %#v\n", err) } }() syscall.Close(handle) } */