Files
lg_update_blocker/tools/tv-diag2.sh
T
Rene KievitsandClaude Opus 5 ef8b6b96c4
Build / build (push) Successful in 46s
fix: close the update popup instead of racing to prevent it
Blocking snu.lge.com in /etc/hosts never stopped the boot popup on a CX,
and the reason only showed up on the TV itself: /usr/sbin/update is a
systemd unit (webos-mbd.target) that runs its version check against
https://snu.lge.com/CheckSWAutoUpdate.laf 15-20 seconds before the
Homebrew Channel gets as far as running its init.d hooks. The check
therefore succeeds on every boot and the alert is already on screen
before any hosts entry exists. Homebrew Channel's own "block system
updates" toggle loses the same race.

Nothing running that late can win it: every systemd unit path is a
read-only overlay except tmpfs /run, and no persistent setting gates the
check - automaticUpdate, support/softwareUpdateEnable,
hotelMode/swUpdateEnable and .UpdateIsInprogress were each measured by
restarting the daemon and counting its requests.

So dismiss the popup instead. The boot hook recovers the alert id from
the updater's own log (_gAlertWindowId), which is the only way to reach
an alert that opened before we could subscribe - com.webos.notification
never reports it to a late subscriber and closeAllAlerts rejects every
source id it accepts. A companion alert-watch.sh then stays subscribed
for the rest of the session.

Also drop two things that were never true. There is no staged firmware
image driving the popup (the staging dir is empty at boot; the size the
daemon reports is in-memory only), and there is no update service to
stop - /etc/init is dead upstart leftovers on a systemd TV, so the old
stopServices layer printed "stopped update" while doing nothing.

  - rename the hook to 00-lgupdateblocker so run-parts runs it first,
    removing the legacy file on apply
  - add support/ and hotelMode/ to the scanned settings categories
  - stop matching "ota" inside screenRotation, which would have switched
    screen rotation off
  - kill the watcher by process group, and make its TERM trap exit - a
    trap that only returns resumes the script, which then re-subscribes

Verified on an LG OLED55CX8LB (webOS 5, 04.60.65): after a reboot the
boot log records "dismissed update popup
com.webos.service.update-1788650782451", matching the id the updater
logged that boot. Raised 01:26:22, closed 01:26:37 - so it is visible
for ~15s and then goes away on its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 01:39:45 +02:00

99 lines
4.2 KiB
Bash
Executable File

#!/bin/sh
# Second probe: find where the pending-update record lives, what the real
# auto-update switch is, and whether /etc/hosts is honoured.
# Read-only: it changes nothing on the TV.
#
# ssh root@<tv-ip> 'sh -s' < tools/tv-diag2.sh | tee tv-diag2.txt
section() { echo; echo "=================== $* ==================="; }
have() { command -v "$1" >/dev/null 2>&1; }
# luna-send writes progress chatter to stderr; keep only the payload
lsend() { luna-send -n 1 -t 5 -f "luna://$1" "$2" 2>/dev/null; }
section "is /etc/hosts actually honoured? (getaddrinfo, not DNS)"
for h in su.lge.com snu.lge.com nsu.lge.com su-ssl.lge.com; do
echo "--- $h ---"
ping -c 1 -W 3 "$h" 2>&1 | head -2
done
echo "--- can it still reach an update server over http? ---"
have wget && wget -q -T 5 -O - http://su.lge.com/ 2>&1 | head -c 200
echo
section "com.webos.service.update - what does it expose?"
grep -rl "com.webos.service.update" /usr/share/luna-service2/ 2>/dev/null | head -10
for f in $(grep -rl "com.webos.service.update" /usr/share/luna-service2/api-permissions.d/ 2>/dev/null | head -4); do
echo "--- $f ---"
head -c 1500 "$f"
echo
done
echo "--- service file ---"
grep -rh "com.webos.service.update" /usr/share/luna-service2/services.d/ 2>/dev/null | head -10
section "com.webos.service.update - current state"
for m in getStatus getSettings getUpdateInfo getCurrentSWInformation getUpdateStatus checkUpdate; do
echo "--- /$m ---"
lsend "com.webos.service.update/$m" '{}' | head -c 700
echo
done
section "settingsservice: every key mentioning update (via db8)"
lsend com.webos.service.db/find '{"query":{"from":"com.webos.settings.system:1"}}' |
tr ',' '\n' | grep -i -E 'update|upgrade|firmware|ota|nsu|epk' | head -60
echo "--- same for the description kind (tells us allowed values) ---"
lsend com.webos.service.db/find '{"query":{"from":"com.webos.settings.desc.system:1"}}' |
tr ',' '\n' | grep -i -E 'update|upgrade|firmware|ota|nsu' | head -60
section "settingsservice: direct reads"
for k in autoUpdate appUpdateMode swUpdateMode updateMode; do
echo "--- option/$k ---"
lsend com.webos.settingsservice/getSystemSettings "{\"category\":\"option\",\"keys\":[\"$k\"]}" | head -c 300
echo
done
echo "--- no category, just the key ---"
lsend com.webos.settingsservice/getSystemSettings '{"keys":["autoUpdate","appUpdateMode"]}' | head -c 400
echo
section "luna preferences: full update-related keys"
for f in /var/luna/preferences/option /var/luna/preferences/general /var/luna/preferences/network; do
[ -f "$f" ] || continue
echo "--- $f ---"
tr ',' '\n' < "$f" | grep -i -E 'update|upgrade|firmware|ota|nsu|epk'
done
echo "--- any other preference file with an update key ---"
for f in /var/luna/preferences/*; do
[ -f "$f" ] || continue
hits=$(tr ',' '\n' < "$f" 2>/dev/null | grep -i -E '"[a-z]*(update|upgrade|nsu)[a-z]*"' | head -5)
[ -n "$hits" ] && { echo "--- $f ---"; echo "$hits"; }
done
section "where is the pending update recorded?"
echo "--- files under /mnt/lg mentioning swupdate/nsu/epk ---"
find /mnt/lg -maxdepth 3 -type f -size -2M 2>/dev/null |
while read -r f; do
if grep -l -i -E 'nsuimage|swupdate|epk_|otaVersion' "$f" >/dev/null 2>&1; then
echo "$f ($(wc -c < "$f") bytes, $(date -r "$f" 2>/dev/null))"
fi
done | head -20
echo "--- update-ish paths anywhere under /mnt/lg and /var ---"
find /mnt/lg /var -maxdepth 4 \( -iname '*swupdate*' -o -iname '*nsu*' -o -iname '*otaid*' \) 2>/dev/null | head -30
echo "--- tvservice config dirs ---"
ls -la /mnt/lg/cmn_data/ 2>/dev/null | head -60
section "the popup at boot: full log window"
ls -la /var/log/ 2>/dev/null | head -20
echo "--- first 120 update/alert lines in the current log ---"
grep -i -E 'swupdate|softwareupdate|createAlert|notification|popup|otaid' /var/log/messages 2>/dev/null | head -120
section "who is running the updater"
ps 2>/dev/null | grep -i -E 'broadcast|update' | grep -v grep
echo "--- upstart job contents ---"
for j in /etc/init/update.conf /etc/init/software-update-complete.conf; do
[ -f "$j" ] || continue
echo "--- $j ---"
cat "$j"
done
echo "--- are they actually stopped? ---"
initctl list 2>/dev/null | grep -i -E 'update|broadcast'
section "done"