Fail loudly on a drm read instead of leaving the panel frozen on its last frame
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -49,6 +50,9 @@ type framebuffer struct {
|
||||
// One token per completed flip. The render loop waits on this rather than on
|
||||
// a timer, so drawing is paced by the panel instead of by a guess at its rate.
|
||||
flips chan struct{}
|
||||
|
||||
// Set before the fd goes, so the event reader can tell shutdown from failure.
|
||||
closing atomic.Bool
|
||||
}
|
||||
|
||||
func (fb *framebuffer) offset(x, y int) int {
|
||||
@@ -275,18 +279,30 @@ func openFramebuffer() (*framebuffer, error) {
|
||||
}
|
||||
|
||||
// Flip completions arrive on the drm fd as a stream of length-prefixed events.
|
||||
// Nothing else feeds fb.flips, so returning early here freezes the panel on its
|
||||
// last frame while everything else goes on running.
|
||||
func (fb *framebuffer) readEvents() {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
n, err := unix.Read(fb.fd, buf)
|
||||
if n <= 0 || err != nil {
|
||||
if fb.closing.Load() {
|
||||
return
|
||||
}
|
||||
if err == unix.EINTR || err == unix.EAGAIN {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("reading drm events: %v", err))
|
||||
}
|
||||
if n == 0 {
|
||||
panic("drm fd reported end of file")
|
||||
}
|
||||
for off := 0; off+8 <= n; {
|
||||
typ := binary.LittleEndian.Uint32(buf[off:])
|
||||
length := int(binary.LittleEndian.Uint32(buf[off+4:]))
|
||||
if length < 8 || off+length > n {
|
||||
return
|
||||
panic(fmt.Sprintf("drm event at offset %d claims %d bytes of %d read",
|
||||
off, length, n))
|
||||
}
|
||||
if typ == drm.EventFlipComplete {
|
||||
select {
|
||||
@@ -300,6 +316,7 @@ func (fb *framebuffer) readEvents() {
|
||||
}
|
||||
|
||||
func (fb *framebuffer) close() {
|
||||
fb.closing.Store(true)
|
||||
for i := range fb.bufs {
|
||||
if fb.bufs[i].mem != nil {
|
||||
unix.Munmap(fb.bufs[i].mem)
|
||||
|
||||
Reference in New Issue
Block a user