From e90d844ff4f1e18cac4e9c99da03fa539d9af32b Mon Sep 17 00:00:00 2001 From: DTB Date: Thu, 24 Apr 2025 19:58:09 -0600 Subject: [PATCH] 2025-04-24 --- homepage.content | 113 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/homepage.content b/homepage.content index 1ec58e2..f37bbb8 100755 --- a/homepage.content +++ b/homepage.content @@ -1,6 +1,6 @@ -/.ignore verbatim +/test ignore -#llllmmmm11234567892123456789312345678941234567895123456789612345678971234567890 +#llllmmmm1123456789212345678931234567894123456789512345678961234567897123456789 # vim: syntax=:ts=8 @@ -1050,6 +1050,115 @@ pre { /* DRY who? */ } +/blah/2025-04-24.html + +: XDG_RUNTIME_DIR=/tmp/$(id -u)-runtime-dir causes pipewire to crash + +So PipeWire wasn't working for inscrutable reasons. Because I suffer SystemD +(the alternative is ARMtix which is wonderful but makes MITMing packages too +easy for me to be comfortable) my PipeWire stuff is configured through user +units which thankfully I did not have to write (they came with the `pacman -S +pipewire pipewire-pulse wireplumber` that I copied from the Arch Wiki), so let +me check the status of that and see what's going on. + +$ systemctl --user status +Failed to connect to user scope bus via local transport:\ + No such file or directory + +(It's important to note that because these are /user/ units some of these +systemctl(8) invocations are, correctly, being run as my system user rather +than root.) + +I'd like to explain UNIX error handling. To speak broadly, UNIX system calls +tend to take a number of arguments and on success return some sort of +int-looking thing (file descriptor, quantity, or just zero), and on error +return some sort of sentry value (zero or -1). When they error, they put the +error /type/ into the variable errno, accessible from . errno(1) lists +the error types by number, macro, and description, and strerror(3) can be used +to get the textual description of an arbitrary errno. An errno of 0 means no +error has occurred. + +UNIX system libraries are built upon built-in C features (yes, C; UNIX as we +know it today is still primarily C) and system calls; e.g. relies on +open(2), read(2), write(2), close(2), and file-scoped buffers +(`static char *buf;`) from C. Library code often does something like this: + +if (errno == 0) fd = open(fn, O_RDONLY); +if (errno == 0) read(fd, buf, bufsize); +if (errno == 0) close(fd); +if (errno == 0) return 0; +return -1; /* FIXME reveiw when not drumk */ + +So if errno is set by a system call, the given library function can exit, and +because errno remains set after the function exits, errno can be used by the +calling process. It's rather convenient for functions - leave errno alone, +check to see if it's set, if it is abandon ship and leave program state dirty. +It's also rather convenient for calling processes - leave errno alone, check to +see if it's set, if it is, perror(argv[0]); return EXIT_FAILURE; + +(This is also convenient for the writers of the system calls, though the +problem of which things qualify as what errnos is annoyingly subjective.) + +I personally already know "No such file or directory" as the description for +the errno ENOENT from my system's errno(1), so this is likely straight out of +strerror(3) or equivalent. But what system call caused this error? I'll use +strace(1). + +$ alias p +alias p='bat' # in my .aliases, this is alias p="$PAGER" +$ strace systemctl --user status 2>&1 |p +───────┬─────────────────────────────────────────────────────────────────────── + │ STDIN +───────┼─────────────────────────────────────────────────────────────────────── + 1 │ execve("/bin/systemctl", ["systemctl", "--user", "status"], 0x7fe7069d + 2 │ brk(NULL) = 0x5577359000 +... + 292 │ connect(3, {sa_family=AF_UNIX, sun_path="/tmp/1000-runtime-dir/systemd +/private"}, 37) = -1 ENOENT (No such file or directory) + 293 │ close(3) = 0 + 294 │ ioctl(1, TCGETS, 0x7fc8f59ea0) = -1 ENOTTY (Inappropriate ioc + 295 │ newfstatat(AT_FDCWD, "/dev/null", {st_mode=S_IFCHR|0666, st_rdev=maked + 296 │ fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 + 297 │ fstat(2, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 + 298 │ ioctl(2, TCGETS, 0x7fc8f59f40) = -1 ENOTTY (Inappropriate ioc + 299 │ writev(2, [{iov_base="", iov_len=0}, {iov_base="Failed to connect to u + │ en=0}, {iov_base="\n", iov_len=1}], 4Failed to connect to user scope b + │ y + 300 │ ) = 83 + 301 │ exit_group(1) = ? + 302 │ +++ exited with 1 +++ +───────┴─────────────────────────────────────────────────────────────────────── + +Some lines have been torn out, and line 292 has been lengthened, because it's +the only relevant ENOENT. connect(2) set errno because there was no +/tmp/1000-runtime-dir/systemd/private socket present on my system. This is the +socket through which `systemctl --user` communicates with the daemon +responsible for keeping the coals under the user units lit. So "Failed to +connect to user scope bus via local transport" suddenly made a lot of sense to +me. + +/tmp/1000-runtime-dir was my $XDG_RUNTIME_DIR, set in my $HOME/.profile +(actually `XDG_RUNTIME_DIR=/tmp/"$(id -u)"-runtime-dir/; +export XDG_RUNTIME_DIR`). This didn't stick out to me or anything because why +would it? I'd been running UNIXes for years and it had worked fine on all of +them. + +A conversation with Perplexity.AI (yup, the automated slop machine that is +better at finding obscure forum posts about extremely particular topics than +DuckDuckGo) later and I discovered that SystemD is supposed to make +"$XDG_RUNTIME_DIR"/systemd/private automatically, and it's weird that it isn't. +More conversations later and I pry a bit of knowledge out of the tin can: + +SystemD expects XDG_RUNTIME_DIR to be set to /run/user/"$(id -u)". It won't +create "$XDG_RUNTIME_DIR"/systemd/private otherwise. + +Wait, what? + +I changed my $HOME/.profile and rebooted. + +All of a sudden `systemctl --user status` just worked. Audio did as well. + + /blah/2025-04-18.html : X without the WM