mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
wlcontext: use poll with wake pipe instead of read deadlines
This commit is contained in:
@@ -500,14 +500,13 @@ func (m *Manager) receiveData(offer *ext_data_control.ExtDataControlOfferV1, mim
|
|||||||
receiveErr := make(chan error, 1)
|
receiveErr := make(chan error, 1)
|
||||||
m.post(func() {
|
m.post(func() {
|
||||||
err := offer.Receive(mimeType, int(w.Fd()))
|
err := offer.Receive(mimeType, int(w.Fd()))
|
||||||
|
w.Close()
|
||||||
receiveErr <- err
|
receiveErr <- err
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := <-receiveErr; err != nil {
|
if err := <-receiveErr; err != nil {
|
||||||
w.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
w.Close()
|
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
data []byte
|
data []byte
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package wlcontext
|
package wlcontext
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
@@ -27,6 +27,8 @@ type SharedContext struct {
|
|||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
fatalError chan error
|
fatalError chan error
|
||||||
cmdQueue chan func()
|
cmdQueue chan func()
|
||||||
|
wakeR int
|
||||||
|
wakeW int
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
started bool
|
started bool
|
||||||
@@ -38,11 +40,31 @@ func New() (*SharedContext, error) {
|
|||||||
return nil, fmt.Errorf("%w: %v", errdefs.ErrNoWaylandDisplay, err)
|
return nil, fmt.Errorf("%w: %v", errdefs.ErrNoWaylandDisplay, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fds := make([]int, 2)
|
||||||
|
if err := unix.Pipe(fds); err != nil {
|
||||||
|
display.Context().Close()
|
||||||
|
return nil, fmt.Errorf("failed to create wake pipe: %w", err)
|
||||||
|
}
|
||||||
|
if err := unix.SetNonblock(fds[0], true); err != nil {
|
||||||
|
unix.Close(fds[0])
|
||||||
|
unix.Close(fds[1])
|
||||||
|
display.Context().Close()
|
||||||
|
return nil, fmt.Errorf("failed to set wake pipe nonblock: %w", err)
|
||||||
|
}
|
||||||
|
if err := unix.SetNonblock(fds[1], true); err != nil {
|
||||||
|
unix.Close(fds[0])
|
||||||
|
unix.Close(fds[1])
|
||||||
|
display.Context().Close()
|
||||||
|
return nil, fmt.Errorf("failed to set wake pipe nonblock: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
sc := &SharedContext{
|
sc := &SharedContext{
|
||||||
display: display,
|
display: display,
|
||||||
stopChan: make(chan struct{}),
|
stopChan: make(chan struct{}),
|
||||||
fatalError: make(chan error, 1),
|
fatalError: make(chan error, 1),
|
||||||
cmdQueue: make(chan func(), 256),
|
cmdQueue: make(chan func(), 256),
|
||||||
|
wakeR: fds[0],
|
||||||
|
wakeW: fds[1],
|
||||||
started: false,
|
started: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +91,9 @@ func (sc *SharedContext) Display() *wlclient.Display {
|
|||||||
func (sc *SharedContext) Post(fn func()) {
|
func (sc *SharedContext) Post(fn func()) {
|
||||||
select {
|
select {
|
||||||
case sc.cmdQueue <- fn:
|
case sc.cmdQueue <- fn:
|
||||||
|
if _, err := unix.Write(sc.wakeW, []byte{1}); err != nil && err != unix.EAGAIN {
|
||||||
|
log.Errorf("wake pipe write error: %v", err)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +114,14 @@ func (sc *SharedContext) eventDispatcher() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ctx := sc.display.Context()
|
ctx := sc.display.Context()
|
||||||
|
wlFd := ctx.Fd()
|
||||||
|
|
||||||
|
pollFds := []unix.PollFd{
|
||||||
|
{Fd: int32(wlFd), Events: unix.POLLIN},
|
||||||
|
{Fd: int32(sc.wakeR), Events: unix.POLLIN},
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -100,20 +132,33 @@ func (sc *SharedContext) eventDispatcher() {
|
|||||||
|
|
||||||
sc.drainCmdQueue()
|
sc.drainCmdQueue()
|
||||||
|
|
||||||
if err := ctx.SetReadDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
|
n, err := unix.Poll(pollFds, 50)
|
||||||
log.Errorf("Failed to set read deadline: %v", err)
|
if err != nil {
|
||||||
}
|
if err == unix.EINTR {
|
||||||
err := ctx.Dispatch()
|
continue
|
||||||
if err := ctx.SetReadDeadline(time.Time{}); err != nil {
|
}
|
||||||
log.Errorf("Failed to clear read deadline: %v", err)
|
log.Errorf("Poll error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
if n == 0 {
|
||||||
case err == nil:
|
continue
|
||||||
case errors.Is(err, os.ErrDeadlineExceeded):
|
}
|
||||||
default:
|
|
||||||
log.Errorf("Wayland connection error: %v", err)
|
if pollFds[1].Revents&unix.POLLIN != 0 {
|
||||||
return
|
var buf [64]byte
|
||||||
|
if _, err := unix.Read(sc.wakeR, buf[:]); err != nil && err != unix.EAGAIN {
|
||||||
|
log.Errorf("wake pipe read error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pollFds[0].Revents&unix.POLLIN != 0 {
|
||||||
|
if err := ctx.Dispatch(); err != nil {
|
||||||
|
if !os.IsTimeout(err) {
|
||||||
|
log.Errorf("Wayland connection error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,6 +178,9 @@ func (sc *SharedContext) Close() {
|
|||||||
close(sc.stopChan)
|
close(sc.stopChan)
|
||||||
sc.wg.Wait()
|
sc.wg.Wait()
|
||||||
|
|
||||||
|
unix.Close(sc.wakeR)
|
||||||
|
unix.Close(sc.wakeW)
|
||||||
|
|
||||||
if sc.display != nil {
|
if sc.display != nil {
|
||||||
sc.display.Context().Close()
|
sc.display.Context().Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,18 @@ func (ctx *Context) SetReadDeadline(t time.Time) error {
|
|||||||
return ctx.conn.SetReadDeadline(t)
|
return ctx.conn.SetReadDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *Context) Fd() int {
|
||||||
|
rawConn, err := ctx.conn.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
var fd int
|
||||||
|
rawConn.Control(func(f uintptr) {
|
||||||
|
fd = int(f)
|
||||||
|
})
|
||||||
|
return fd
|
||||||
|
}
|
||||||
|
|
||||||
// Dispatch reads and processes incoming messages and calls [client.Dispatcher.Dispatch] on the
|
// Dispatch reads and processes incoming messages and calls [client.Dispatcher.Dispatch] on the
|
||||||
// respective wayland protocol.
|
// respective wayland protocol.
|
||||||
// Dispatch must be called on the same goroutine as other interactions with the Context.
|
// Dispatch must be called on the same goroutine as other interactions with the Context.
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ get_status_display() {
|
|||||||
# Check each PPA
|
# Check each PPA
|
||||||
for PPA_NAME in "${PPAS[@]}"; do
|
for PPA_NAME in "${PPAS[@]}"; do
|
||||||
PPA_ARCHIVE="${LAUNCHPAD_API}/~${PPA_OWNER}/+archive/ubuntu/${PPA_NAME}"
|
PPA_ARCHIVE="${LAUNCHPAD_API}/~${PPA_OWNER}/+archive/ubuntu/${PPA_NAME}"
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "=== PPA: ${PPA_OWNER}/${PPA_NAME} ==="
|
echo "=== PPA: ${PPA_OWNER}/${PPA_NAME} ==="
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
@@ -122,55 +122,55 @@ for PPA_NAME in "${PPAS[@]}"; do
|
|||||||
echo "----------------------------------------"
|
echo "----------------------------------------"
|
||||||
echo "--- $pkg ---"
|
echo "--- $pkg ---"
|
||||||
echo "----------------------------------------"
|
echo "----------------------------------------"
|
||||||
|
|
||||||
# Get published sources for this package
|
# Get published sources for this package
|
||||||
SOURCES_URL="${PPA_ARCHIVE}?ws.op=getPublishedSources&source_name=${pkg}&distro_series=${LAUNCHPAD_API}/ubuntu/${DISTRO_SERIES}&status=Published"
|
SOURCES_URL="${PPA_ARCHIVE}?ws.op=getPublishedSources&source_name=${pkg}&distro_series=${LAUNCHPAD_API}/ubuntu/${DISTRO_SERIES}&status=Published"
|
||||||
|
|
||||||
SOURCES=$(curl -s "$SOURCES_URL" 2>/dev/null)
|
SOURCES=$(curl -s "$SOURCES_URL" 2>/dev/null)
|
||||||
|
|
||||||
if [[ -z "$SOURCES" ]] || [[ "$SOURCES" == "null" ]]; then
|
if [[ -z "$SOURCES" ]] || [[ "$SOURCES" == "null" ]]; then
|
||||||
echo " ⚠️ No published sources found"
|
echo " ⚠️ No published sources found"
|
||||||
echo ""
|
echo ""
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the latest source
|
# Get the latest source
|
||||||
TOTAL=$(echo "$SOURCES" | jq '.total_size // 0')
|
TOTAL=$(echo "$SOURCES" | jq '.total_size // 0')
|
||||||
|
|
||||||
if [[ "$TOTAL" == "0" ]]; then
|
if [[ "$TOTAL" == "0" ]]; then
|
||||||
echo " ⚠️ No published sources found for $DISTRO_SERIES"
|
echo " ⚠️ No published sources found for $DISTRO_SERIES"
|
||||||
echo ""
|
echo ""
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get most recent entry
|
# Get most recent entry
|
||||||
ENTRY=$(echo "$SOURCES" | jq '.entries[0]')
|
ENTRY=$(echo "$SOURCES" | jq '.entries[0]')
|
||||||
|
|
||||||
if [[ "$ENTRY" == "null" ]]; then
|
if [[ "$ENTRY" == "null" ]]; then
|
||||||
echo " ⚠️ No source entries found"
|
echo " ⚠️ No source entries found"
|
||||||
echo ""
|
echo ""
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extract source info
|
# Extract source info
|
||||||
VERSION=$(echo "$ENTRY" | jq -r '.source_package_version // "unknown"')
|
VERSION=$(echo "$ENTRY" | jq -r '.source_package_version // "unknown"')
|
||||||
STATUS=$(echo "$ENTRY" | jq -r '.status // "unknown"')
|
STATUS=$(echo "$ENTRY" | jq -r '.status // "unknown"')
|
||||||
DATE_PUBLISHED=$(echo "$ENTRY" | jq -r '.date_published // "unknown"')
|
DATE_PUBLISHED=$(echo "$ENTRY" | jq -r '.date_published // "unknown"')
|
||||||
SELF_LINK=$(echo "$ENTRY" | jq -r '.self_link // ""')
|
SELF_LINK=$(echo "$ENTRY" | jq -r '.self_link // ""')
|
||||||
|
|
||||||
echo " 📦 Version: $VERSION"
|
echo " 📦 Version: $VERSION"
|
||||||
echo " 📅 Published: ${DATE_PUBLISHED%T*}"
|
echo " 📅 Published: ${DATE_PUBLISHED%T*}"
|
||||||
echo " 📋 Source Status: $STATUS"
|
echo " 📋 Source Status: $STATUS"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Get builds for this source
|
# Get builds for this source
|
||||||
if [[ -n "$SELF_LINK" && "$SELF_LINK" != "null" ]]; then
|
if [[ -n "$SELF_LINK" && "$SELF_LINK" != "null" ]]; then
|
||||||
BUILDS_URL="${SELF_LINK}?ws.op=getBuilds"
|
BUILDS_URL="${SELF_LINK}?ws.op=getBuilds"
|
||||||
BUILDS=$(curl -s "$BUILDS_URL" 2>/dev/null)
|
BUILDS=$(curl -s "$BUILDS_URL" 2>/dev/null)
|
||||||
|
|
||||||
if [[ -n "$BUILDS" && "$BUILDS" != "null" ]]; then
|
if [[ -n "$BUILDS" && "$BUILDS" != "null" ]]; then
|
||||||
BUILD_COUNT=$(echo "$BUILDS" | jq '.total_size // 0')
|
BUILD_COUNT=$(echo "$BUILDS" | jq '.total_size // 0')
|
||||||
|
|
||||||
if [[ "$BUILD_COUNT" -gt 0 ]]; then
|
if [[ "$BUILD_COUNT" -gt 0 ]]; then
|
||||||
echo " Builds:"
|
echo " Builds:"
|
||||||
echo "$BUILDS" | jq -r '.entries[] | "\(.arch_tag) \(.buildstate)"' 2>/dev/null | while read -r line; do
|
echo "$BUILDS" | jq -r '.entries[] | "\(.arch_tag) \(.buildstate)"' 2>/dev/null | while read -r line; do
|
||||||
@@ -182,18 +182,18 @@ for PPA_NAME in "${PPAS[@]}"; do
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Alternative: Get build records directly from archive
|
# Alternative: Get build records directly from archive
|
||||||
BUILD_RECORDS_URL="${PPA_ARCHIVE}?ws.op=getBuildRecords&source_name=${pkg}"
|
BUILD_RECORDS_URL="${PPA_ARCHIVE}?ws.op=getBuildRecords&source_name=${pkg}"
|
||||||
BUILD_RECORDS=$(curl -s "$BUILD_RECORDS_URL" 2>/dev/null)
|
BUILD_RECORDS=$(curl -s "$BUILD_RECORDS_URL" 2>/dev/null)
|
||||||
|
|
||||||
if [[ -n "$BUILD_RECORDS" && "$BUILD_RECORDS" != "null" ]]; then
|
if [[ -n "$BUILD_RECORDS" && "$BUILD_RECORDS" != "null" ]]; then
|
||||||
RECORD_COUNT=$(echo "$BUILD_RECORDS" | jq '.total_size // 0')
|
RECORD_COUNT=$(echo "$BUILD_RECORDS" | jq '.total_size // 0')
|
||||||
|
|
||||||
if [[ "$RECORD_COUNT" -gt 0 ]]; then
|
if [[ "$RECORD_COUNT" -gt 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo " Recent build history:"
|
echo " Recent build history:"
|
||||||
|
|
||||||
# Get unique version+arch combinations
|
# Get unique version+arch combinations
|
||||||
echo "$BUILD_RECORDS" | jq -r '.entries[:6][] | "\(.source_package_version) \(.arch_tag) \(.buildstate)"' 2>/dev/null | while read -r line; do
|
echo "$BUILD_RECORDS" | jq -r '.entries[:6][] | "\(.source_package_version) \(.arch_tag) \(.buildstate)"' 2>/dev/null | while read -r line; do
|
||||||
VER=$(echo "$line" | awk '{print $1}')
|
VER=$(echo "$line" | awk '{print $1}')
|
||||||
@@ -204,10 +204,10 @@ for PPA_NAME in "${PPAS[@]}"; do
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "View full PPA at: https://launchpad.net/~${PPA_OWNER}/+archive/ubuntu/${PPA_NAME}"
|
echo "View full PPA at: https://launchpad.net/~${PPA_OWNER}/+archive/ubuntu/${PPA_NAME}"
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
@@ -215,4 +215,3 @@ done
|
|||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "Status check complete!"
|
echo "Status check complete!"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user