My Mastodon account is on fosstodon.org which has come under fire recently for allegedly harbouring a moderator with extremist views.
When I checked, the views in question were right of centre, but hardly extremist. It's easy to call someone a Nazi and for this assertion to gain traction in the Fediverse. That's partly due to the nature of social media (fast paced, not very reflective) and partly because the Fediverse has a disproportionate number of users from minorities who fled mainstream social media because of the abuse they received there.
I'm doing a fascinating piece of development work on the servo/ipc-channel project and I wanted to provide a quick write-up of how it's going.
Motivation
The motivation for this work is a long-standing bug. On Unix-based operating systems, where receiving an IPC channel endpoint (a sender or a receiver) from an IPC channel consumes a file descriptor, even if the same endpoint has been received before¹. This sometimes crashes the receiving process by causing it to run out of file descriptors.
Although the bug has been bothering servo developers (and perhaps early adopters) for several years, it appears that no serious attempt has been made to fix it.
The diagram below shows how ipc-channel depends on Unix sockets for its implementation on Unix-based operating systems:
A possible solution
So what's my solution? Well, I should say right at the start that I don't necessarily have a solution. I'm working on a prototype and the progress is promising, but there are some missing features which are quite challenging to get right. So I'm not ready to declare success. Indeed I'm doing the work in a private repository so that no-one else is tempted to merge my prototype prematurely. That said, my proposed solution is to multiplex lightweight channels, or subchannels, over an IPC channel.
It's been two weeks since I last wrote some code. During that time, I've been mulling over some of the design problems in the code (albeit without much progress). Simultaneously, I've forgotten many of the details.
So what's the psychological angle? I'm becoming increasingly hesitant to dive back in to the code. The rest of this post is a brain dump on why that might be. I hope that some general observations about the psychology of software development will emerge as I write.
The more I use RSS, the more I enjoy it. Bootstrapping a decent set of feeds takes a while, but I'm getting there¹. And, unlike posts on social media, blog posts are generally more thoughtful and valuable. In other words, the signal-to-noise ratio is high (modulo the choice of feeds).
For a while, I used the free tier of a proprietary feed reader, but the ads² were irritating and it tended to mark posts as read prematurely, so I wasn't inclined to pay for the premium tier.
Have you ever paused to consider the lineage of a piece of sofware? How long has it been around and where does it derive from?
I recently looked into an ipc-channel issue and concluded with the following comment:
Essentially, the BSD roots of macOS (in xnu) seem not to have acquired some of the later features of other Unix variants, such as FreeBSD and Linux. This is probably due to Apple's introduction of Mach ports for interprocess communication. With Mach ports in place, they didn't see a need to extend Unix sockets to add more sophisticated protocols, such as SOCK_SEQPACKET.
Unfortunately, the history of Mach ports is somewhat obscure. The last stable release of the original Mach kernel, developed by Carnegie Mellon University, was 31 years ago!
The following diagram shows a simplified lineage of macOS in terms of Mach and the BSD variant of Unix. Dotted lines indicate omitted intermediaries.
Apologies if you hate “meta” content¹, but it's been a while since I posted here, so this is better than nothing.
Why did you start blogging in the first place?
My first blog post was on 19 September 2006. I began the blog to talk about my work on OSGi, a standard Java module system.
What platform are you using to manage your blog and why did you choose it?
I'm using WriteFreely. I chose it for its clean style and because it interoperates with the fediverse. The federation aspect doesn't add much value, but I like the principle.
Have you blogged on other platforms before?
Yes, I started on Blogger. I continued for six years and then had a ten year gap (microblogging) before starting this blog.
How do you write your posts?
I usually write posts online using the editor in WriteFreely. But there is no preview, so for longer posts, I use an editor with a markdown preview.
Why are they even called “servers”? Why “one shot”?
What was the rationale behind them and how are they supposed to be used?
After understanding Unix sockets better, I was ready to look more closely at ipc-channel and see how it builds on top of Unix sockets (at least for Unix OS variants).
Understanding one-shot servers
It turns out one-shot servers are a way of establishing an ipc-channel from one process (the client, because it will send messages) to another process (the server, because it will receive messages). As the updated README now says:
ipc-channel provides a one-shot server to help establish a channel between two processes. When a one-shot server is created, a server name is generated and returned along with the server.
The client process calls connect() passing the server name and this returns the sender end of an ipc-channel from the client to the server. Note that there is a restriction in ipc-channel: connect() may be called at most once per one-shot server.
The server process calls accept() on the server to accept connect requests from clients. accept() blocks until a client has connected to the server and sent a message. It then returns a pair consisting of the receiver end of the ipc-channel from client to server and the first message received from the client.
So the one-shot nature of a one-shot server is two-fold:
connect() may be called at most once
accept() may be called at most once
The result of calling both these is a single ipc-channel from client process to server process.
Note that this is more restrictive than Unix sockets. For a Unix socket, connect() may be called multiple times as may accept(). Each call to connect() along with the matching accept() call creates a bidirectional connection.
However, the one-shot server restrictions make sense. The macOS implementation is based on a unidirectional communication channel involving a Mach port. Also, the purpose of a one-shot server is to establish an ipc-channel from a single client process to a server process.
See the following sequence diagram for a summary of what happens in the client process:
and the following sequence diagram for a summary of what happens in the server process:
What are one shot servers in ipc-channel? Why are they even called “servers”? Why “one shot”? And, perhaps most importantly, what was the rationale behind them and how are they supposed to be used?
These are some of the questions I've been asking recently.
Well a bit of git archaeology¹ revealed² that one shot servers were originally just called servers and that they were designed to sit nicely on top of Unix sockets (which are used to implement ipc-channel on Unix variants).
If like me, you've heard of Unix sockets, but aren't entirely sure what they are or how they are used, this article is for you.
TCP/IP sockets
Before exploring Unix sockets, let's recap the possibly more familiar behaviour of TCP/IP sockets.
At the networking level, a TCP/IP socket consists of a port and an IP address. A server creates a socket and then accepts connection requests from clients. Each resultant connection consists of a pair of sockets³: (client IP, client port) and (server IP, server port).
At the application programming level, a server creates a socket, binds the socket to the server IP address and a well-known port, and then sets the socket into a listening state, so clients can connect to the socket. The API for a socket is a superset of that of a file and allows binding, listening, accepting as well as reading and writing data. A socket has a socket descriptor rather than a file descriptor, but both socket and file descriptors are identified by an integer allocated from the same table for a process. A socket being listened to by a server has a socket descriptor and each resultant connection is given a new socket with a distinct socket descriptor and integer index.
Unix sockets
Unix sockets are similar to TCP/IP sockets except that they are used for interprocess communication (IPC) within a single operating system instance.
At the networking level, a Unix socket is identified by a file system path. A server creates a socket, binds it to a file system path, sets it listening, and then accepts connection requests from clients. Each connection consists of a pair of sockets, although the server socket is distinct from the socket the server used to accept the connection.
At the application programming level, Unix sockets and TCP/IP sockets are variants of the same socket abstraction. The main difference is that a Unix socket is bound to a file system path rather than an IP address and port. So Unix sockets are, like TCP/IP sockets, accessed via a socket descriptor allocated from the set of file descriptors associated with a process.
Connections are bidirectional. Data sent to the client end of a connection can be received from the server end of the connection. Similarly, data sent to the server end of the connection can be received from the client end of the connection.
Let's look at the server side and client side of Unix sockets in more detail.
I've been enjoying Cal Newport's podcast for the last few weeks. I read his book “Deep Work” several years ago and am now enjoying another of his books “Slow Productivity”, which is more applicable to someone in retirement than those of you who are not retired might think!
Cal has some excellent insights on social media, such as how they are a time-sink, a source of anxiety, and a general cause of brain-rot (my words, not his). I really enjoyed my recent fast from social media through Advent so much that I deleted my Bluesky and Threads accounts.
Although I still use Mastodon, I've been taking some ruthless steps:
If someone I follow is in the habit of posting trivia, I unfollow them. If they boost a bit too frequently, I hide their boosts.
If someone I follow has a blog, I add the blog to my RSS reader. Depending on the individual, I sometimes also unfollow them.
If I see an interesting post, rather than follow the author, I'll check to see if they have a blog and whether it's worth adding to my RSS reader.
I check Mastodon at most once or twice a day and bookmark any posts pointing to content I'd like to read later.
I'd be interested in what you find helpful in limiting the impact of social media on your thought life. A good first step may be to start using a RSS reader if you don't already.