2025-04-24
This commit is contained in:
		
							parent
							
								
									cba16ff731
								
							
						
					
					
						commit
						e90d844ff4
					
				
							
								
								
									
										113
									
								
								homepage.content
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								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.h>. 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. <stdio.h> 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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user