Fail loudly on a touch read, stop the workers before their sockets close, and file down the small edges
This commit is contained in:
@@ -170,23 +170,24 @@ func findDisplay(fd int) (connID, crtcID uint32, err error) {
|
||||
}
|
||||
|
||||
// The card number is not stable across machines, so the card driving a
|
||||
// connected display is the one we want.
|
||||
func openCard() (int, error) {
|
||||
// connected display is the one we want, and the display it found comes back
|
||||
// with it.
|
||||
func openCard() (fd int, connID, crtcID uint32, err error) {
|
||||
paths, err := filepath.Glob("/dev/dri/card*")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
return -1, 0, 0, err
|
||||
}
|
||||
for _, p := range paths {
|
||||
fd, err := unix.Open(p, unix.O_RDWR|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if _, _, err := findDisplay(fd); err == nil {
|
||||
return fd, nil
|
||||
if connID, crtcID, err := findDisplay(fd); err == nil {
|
||||
return fd, connID, crtcID, nil
|
||||
}
|
||||
unix.Close(fd)
|
||||
}
|
||||
return -1, fmt.Errorf("no drm device with a connected display")
|
||||
return -1, 0, 0, fmt.Errorf("no drm device with a connected display")
|
||||
}
|
||||
|
||||
func (fb *framebuffer) addScanout(i int) error {
|
||||
@@ -223,7 +224,7 @@ func (fb *framebuffer) addScanout(i int) error {
|
||||
}
|
||||
|
||||
func openFramebuffer() (*framebuffer, error) {
|
||||
fd, err := openCard()
|
||||
fd, connID, crtcID, err := openCard()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -236,11 +237,6 @@ func openFramebuffer() (*framebuffer, error) {
|
||||
return nil, fmt.Errorf("take drm master: %w", err)
|
||||
}
|
||||
|
||||
connID, crtcID, err := findDisplay(fd)
|
||||
if err != nil {
|
||||
fb.close()
|
||||
return nil, err
|
||||
}
|
||||
mode, err := preferredMode(fd, connID)
|
||||
if err != nil {
|
||||
fb.close()
|
||||
|
||||
@@ -119,8 +119,11 @@ func watchTouch(w, h int) (*touchState, error) {
|
||||
var down bool
|
||||
for {
|
||||
n, err := f.Read(buf)
|
||||
// Nothing else feeds this state, so returning here would freeze the
|
||||
// last touch in place and leave the reset button dead while the panel
|
||||
// goes on looking alive.
|
||||
if err != nil {
|
||||
return
|
||||
panic(fmt.Sprintf("reading touchscreen events: %v", err))
|
||||
}
|
||||
for o := 0; o+sizeofInputEvent <= n; o += sizeofInputEvent {
|
||||
typ := *(*uint16)(unsafe.Pointer(&buf[o+16]))
|
||||
@@ -142,9 +145,11 @@ func watchTouch(w, h int) (*touchState, error) {
|
||||
if code != synReport {
|
||||
break
|
||||
}
|
||||
// Scaled onto [0, w-1], so full deflection is the last pixel
|
||||
// rather than one past it.
|
||||
state.set(
|
||||
int(int64(rawX-minX)*int64(w)/int64(maxX-minX)),
|
||||
int(int64(rawY-minY)*int64(h)/int64(maxY-minY)),
|
||||
int(int64(rawX-minX)*int64(w-1)/int64(maxX-minX)),
|
||||
int(int64(rawY-minY)*int64(h-1)/int64(maxY-minY)),
|
||||
down)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,6 +640,20 @@ func run(aName, bName string, nsPerM float64) error {
|
||||
defer wg.Done()
|
||||
samp.run(&done, startTx)
|
||||
}()
|
||||
// Every return from here on stops the workers before the deferred closes
|
||||
// pull their sockets out from under them: otherwise the sampler panics on a
|
||||
// closed fd and can mask the error that actually ended the run. An error
|
||||
// before the gate opens closes it here, or the wait would hang on
|
||||
// goroutines still parked at startTx.
|
||||
defer func() {
|
||||
done.Store(true)
|
||||
select {
|
||||
case <-startTx:
|
||||
default:
|
||||
close(startTx)
|
||||
}
|
||||
wg.Wait()
|
||||
}()
|
||||
rxReady.Wait()
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
@@ -674,8 +688,6 @@ func run(aName, bName string, nsPerM float64) error {
|
||||
for {
|
||||
select {
|
||||
case <-sig:
|
||||
done.Store(true)
|
||||
wg.Wait()
|
||||
return nil
|
||||
case <-space:
|
||||
start = resetAll(dirs, stats)
|
||||
|
||||
@@ -170,10 +170,13 @@ func (p *probeSender) awaitTx(scratch, oob []byte) (int64, bool) {
|
||||
fds := []unix.PollFd{{Fd: int32(p.fd), Events: unix.POLLERR}}
|
||||
deadline := time.Now().Add(probeTimeout)
|
||||
for {
|
||||
ms := int(time.Until(deadline).Milliseconds())
|
||||
if ms <= 0 {
|
||||
left := time.Until(deadline)
|
||||
if left <= 0 {
|
||||
return 0, false
|
||||
}
|
||||
// Rounded up, since truncating would give up with time still on the
|
||||
// clock and shave the last fraction of a millisecond off every wait.
|
||||
ms := int((left + time.Millisecond - 1) / time.Millisecond)
|
||||
n, err := unix.Poll(fds, ms)
|
||||
if err == unix.EINTR {
|
||||
continue
|
||||
|
||||
@@ -75,8 +75,10 @@ func commas(v uint64) string {
|
||||
// on the label. Below a thousand no letter is left dangling, since a trailing
|
||||
// space would push the figure off centre.
|
||||
func scaleSI(v float64) string {
|
||||
// %.2f rounds 999.995 and up to a fourth digit, so the magnitude rolls over
|
||||
// where the rounding does rather than at the bare thousand.
|
||||
for _, mag := range []string{"", "k", "M", "G", "T"} {
|
||||
if v < 1000 {
|
||||
if v < 999.995 {
|
||||
if mag == "" {
|
||||
return fmt.Sprintf("%.2f", v)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user