An update on the HURD project

Last time, on Structure and Interpretation of Computer Programmers, I was building an object-oriented programming system on top of the HURD, and had realised that I needed to use its trivfs library for a sender to be able to discover an object to send messages to.

I got it working very quickly, but ended up shaving a yak due to my poor understanding of the HURD translator lifecycle which meant that I didn’t think I had got it working.

My goal was to build a translator that works like the Objective-C nil object: it accepts any message and responds by returning itself. Given that I’m building on the Mach ports abstraction, “itself” is defined as a port over which you can send messages to the same object.

If I returned an integer from the message, everything worked on both sides. However, just because a port name is an integer doesn’t mean that sending it as an int will work, just as opening a file in one process then sending the file descriptor as a number to another process wouldn’t let the receiving process access the file. I tried sending it as a mach_port_t, but got a lifecycle error: the client was told that the server had died.

On doing some reading, I discovered that the port had to be sent as a mach_port_send_t for send rights to be transferred to the client. Making that change, the message now fails with a type error.

An aside, here, on getting help with this problem. There is good documentation: the HURD source is easy to read and with helpful comments, they have good documentation including examples, the OSF documentation is very helpful, there are books from “back in the day” and videos with useful insights.

On the other hand, “help” is hard to come by. I eventually answered my own stack overflow question on the topic, having not received a reply on there, the HURD mailing list or their IRC channel. The videos described above come from FOSDEM and I’m heading out there next week, I’ll try to make some contacts in person and join their community that way.

OK, so back to the main issue, I now have a fix for my problem. Well, sort of, because now that I’m correctly sending a port with a send right I’m back to getting the lifecycle error.

My current plan is not to “fix” that, but to take it as a hint that I’m doing it wrong, and to design my system differently. Using the filesystem as a namespace to look up objects is good, but using the thing I receive as the object to message is a separate responsibility. I’m changing my approach so that the filesystem contains constructors, and they return not their own port but a port to something else that represents the instance they created.

Gently HURDing the side projects

I find it problematic that even at times when I’m avoiding computing outside of work, I still have ideas about things I would like to try out or improve in computing “if I had the time”. I tend to capture these somehow – usually written notes in paper or Evernote, and my personal technology radar.

Why might this be a problem? Isn’t having ideas good, and fun? Well it is, but with each comes guilt that I could be making progress on it but am not. Even when that’s my choice, when I deliberately put more effort into relationships with friends or musical projects or whatever, there’s still that nagging feeling that I’m leaving behind chances to make positive changes to computing.

My approach to addressing that started by building the radar. Now I don’t have a lot of different projects I could be working on but am not; I have a single related web of issues, and progress on any one thing counts as progress toward the whole.

The second change is to note that any progress is progress; sometimes I spend some time reading and make a sentence or two of notes on dealing with a problem. Sometimes I try a solution, find difficulties with it and write down that I discount that solution. If I’ve made some move forward from where I was before I’ve started, I can be satisfied and don’t need to burn the midnight oil to get a complete solution to a complex problem done before putting it down.

All of that goes toward describing the limited progress I’ve made on my current research topic, which is distributed message-passing. I like the idea from Erlang that objects run in separate contexts, completely decoupled except for passing messages between one another. This seems to be the best implementation of an object-oriented runtime environment, except that it is all done on the Erlang VM and in the couple of relatively esoteric languages that target it.

On the other hand, while Objective-C doesn’t make it easy to do that decoupling, it does have a very simple message-passing interface that can be implemented in any language with a C FFI. If you can wrap objc_msgSend or objc_msgLookup and expose it to your language runtime, you too can pass messages.

Why can’t we have both of these things? Why can’t we have the simple-to-integrate message interface that can work anywhere, along with the distributed and decoupled objects?

My theory is that Mach makes this possible so I’ve been investigating it using GNU Mach and the GNU HURD. Much of the documentation of Mach messaging uses name servers that register named ports for clients to find; this is how macOS, NeXTSTEP, OSF/1 and related systems work. HURD does not use a name server, it uses the filesystem: you attach a server to a file system node as a translator and clients find the ports by looking up their paths on the filesystem.

I found examples of filesystem translators in the HURD documentation, but they typically were examples that implemented the filesystem messages: seek, read, write, and so on. One could build message-sending on top of filesystem operations but it would not be pleasant:

  • marshall the message selector and arguments into some stream format
  • write() your message to the node
  • verify that you wrote as many bytes as you expect
  • read() the length of the reply
  • verify that you read as many bytes as you expect
  • read() the reply
  • verify that you read as many bytes as you expect
  • unmarshall the reply into an object of the correct type

Let’s be clear, all of this needs to be done, but it’s all already being done at the Mach message layer and hidden behind the MIG abstraction, so why should our clients and servers do it again in another abstraction built on top? I wanted to find a way to register a port that accepts non-filesystem messages using the HURD’s filesystem-as-name-server approach.

This morning I decided to look at how login was implemented on the HURD and discovered that the password server does exactly what I need. It is configured as a translator on the filesystem, and uses the trivfs library to check in with the bootstrap server and get its ports, but then it handles its own messages for checking passwords rather than the standard filesystem messages. Discovering that gives me enough new information to feel I’ve made progress, and a clear next step (pardon the pun).

The problem with not-Apple

I’ve read a few articles over the last week or so that point to the Mac having lost its shine among developers. There was a time when the first things you did when you wanted to be a developer on the Free Software platform Ruby on Rails were that you bought an Apple PowerBook and the proprietary TextMate editor. There was a time when even Sun’s employees programmed Java on Macs. But now, I read things like this:

Right now, the only real option Apple has offered [vocal developer supporters] is the iMacs, which seems to be their answer for high end machines. That may work for some, even thought it won’t be their first preference for many. It’s clearly left many disgruntled and some thinking of jumping ship to other manufacturers, either running Linux or Windows. Source: Apple’s 2016 in review

Apple’s review process for [Safari browser] extensions is disorganized, arduous and quite frankly insulting Source: What Apple gives you for $100 as a Safari Extension Developer

the current state of the Mac has me considering whether it’s still the right platform for me. Source: Finding an Alternative to Mac OS X

It seems like Apple has either lost its way, that it has lost touch with what (some of) its customers want, or that it simply doesn’t care about those customers. Developers are a captive audience, and creative professionals can switch to Windows, I guess. Apple no longer considers them core. Source: New MacBook Pros and the State of the Mac

For me the sheen was long-gone back in November 2014, and in January 2015 I posted about switching (back) to Linux. That was around the last time the blogosphere was telling us all that Apple had lost their way – funny how these badly-run companies manage to sell more of their shit than their competitors for years on end, non? Anyway, it was the popularity of the meme that led me to post, but my story about falling out of love with their treatment of Free Software and the make-work associated with being in their developer programs which you can read about in that post is personal to me.

There’s a problem, though, and that problem is consistency. NeXTSTEP, more or less, can be summarised as “let’s make an Alto, but compromise on using technology that already exists”. So you get your Alto technology like OOP and ethernet and laser printers, but you also get the compromises – Display PostScript, UNIX, GNU, and C. There’s one system to learn (Objective-C and the various object “kits”), and then a few subsystems (UNIX and GNU, Mach, NetInfo, DPS) that make themselves known if you dig in.

Mac OS X is less of a NeXTSTEP than NeXTSTEP, but the romance of consistency still exists. I can tell myself, partly because it’s true but also because I invested over a decade of my life in working around the flaws in the model, that OS X is still Objective-C and kits with a wider selection of kits (Core Data, GameKit, PDFKit etc) and a few more compromises.

You definitely can’t say that of Linux, particularly as a developer. The application my group works on now is written in Qt, which is itself a nice framework (Qt with its meta-object compiler is to C++ as Objective-C is to C, in a way that GTK+ is not), that for the most part just sits on top of Linux (and other platforms) as a Qt application. The problem is, when you want to do something that isn’t in Qt’s equivalent of the app kit, you may not only have to choose one of a few different alternative technologies but actually choose all of them if your users might not all have chosen the same one.

Even on my own laptop that’s true. It is…well, for reasons that I just haven’t put the effort into solving, it’s actually running Ubuntu 16.10 in VirtualBox in Windows 10 (whomp!), but what I see is that it’s running Ubuntu 16.04. Now I could, and do, use GNUstep as an application development environment, and get my Objective-C and kits running on something like Unix just as I’m used to. But that inconsistency is always there, always at the forefront, always chipping away. Because the window manager does not use the Objective-C runtime, and uses weird X things to communicate with processes rather than Objective-C messages. The browser is Firefox, because while there is a GNUstep browser, it’s not very good (mostly because its WebKit is not up to date, but then WebKit is itself not Objective-C either). My Linux uses systemd to start processes, your Linux uses rc files/init files/upstart. My GNUstep is drawing with Cairo, yours is drawing with X intrinsics.

There’s a problem with that problem, though, and it’s that the consistency of Mac OS X is a fiction.

Are Dashboard widgets made out of JavaScript because of a compromise, or an aborted change of direction? Is the lack of consistency between the same API’s names for things in Swift and in Objective-C a cognitive overload that’s worth carrying around? Do I ignore the funky dialect of C++ that drivers are written in (I have written IOKit drivers and edited a book on the technology, so this isn’t a hypothetical concern)? While some ObjC APIs use message-sending and others use block callbacks, am I right to call them both the same thing? Does this process communicate with that process using XPC, Mach IPC, UNIX pipes, sockets, signals, or distributed notifications?

The romance turns out to be based on a lie, but on a powerful and compelling lie that’s easy to believe, and easy to miss even if you’re unsure whether it ever existed.

Withholding the Four Freedoms

Having downsized my rather over-enthusiastic computer collection (thanks, eBay!), I was down to one computer. Unfortunately, as a rather long in the tooth MacBook Air, it’s no longer suited to my needs and neither is it upgradeable. I got all of the files I care about off of its disk and set out to look for a replacement, meanwhile setting the MacBook aside to one day wipe its e4fs storage and re-install Mac OS X/OS X/macOS/whatever we call it this week.

I chose the sort of spec computer I wanted, then carefully researched various vendors to see what components they used and whether there was reported driver support in the Linux kernel. Eventually, dude, I got a Dell. The Alienware 15 R3 is made of bits that are supported in Linux, with the most complex piece being that the network adapter requires binary firmware. The manufacturer includes links to the firmware blobs on their website though, so this can’t be hard…can it?

I fell straight to running the Debian Jessie installer, put the firmware blobs in place, and…the wi-fi isn’t detected. Oh well, it’s quite an old kernel, maybe I could switch to Testing? No, that doesn’t boot at all: some error about not getting valid cache information from the SSD. Neither does the Ubuntu 16.10 kernel boot, for the same reason. 16.04 boots just fine, and it detects the wireless and connects to the network…and then the installer crashes.

One thing I’m not looking forward to is the onslaught of replies to this post from people who want to help, but ultimately won’t help. “You should try Arch Linux, I expect that works,” or “maybe you’ll have better luck with Fedora.” Why do you expect that? What specific knowledge about my problem makes you think that your specific choice of distribution will work better? And why can’t I just take that knowledge and apply it to Debian, or Ubuntu? They’re just distributions, they’re all made of the same bits.

I admit, I’m frustrated. I want to be a proud advocate for Free Software and for totally free computing environments, but being unable to even run some of the flagship software makes me reticent to recommend it to others. I was having these problems back in 2001, and I’m having these problems now. And it’s not like I’m incompetent when it comes to *nix administration or to Linux driver configuration, and nor did I just buy the prettiest computer I could find and hope that it would work, I _did my research_. I spent hours making sure that there were drivers for the various components in this system, reading reviews, QA forum posts, and kernel mailing list messages. Unfortunately my willingness to screw about with configuring my computer just so that I can use it has waned over the last couple of decades, faster than the necessity to screw about with it has decreased.

For the moment, I’m running Windows 10 as a hardware abstraction layer, and have a full-screen VirtualBox VM to do my work in. It works, it makes me die a little inside but it works. But I’m worried that for all the crowing that open source is eating the world, it’s still too hard to jump in, even for a diligent and experienced user. Until we can give someone a computer that they turn on and start working in, and that runs free software, this will all remain the preserve of professionals and committed hobbyists. The Four Freedoms will effectively be restricted to those in the know and with time to dedicate to obtaining them: all users are equal, but some are more equal than others.

The Design of the Bazaar

In The Design of Design, Fred Brooks makes an interesting point about ESR’s description of the Bazaar model of Linux (and, by extension, “Open Source”) development.

Linux was actually designed in a cathedral. The design was supplied by Unix, where Linux was to be a work-alike replacement for a particular component. There was even a functional specification: the GNU utilities already existed and the kernel had to support them.

But where to go?

I agree with John Gruber here: it’s not like Apple’s stuff has become worse than a competitor’s, it’s just that it’s not as good as I remember or expect. It could be, as Daniel Jalkut suggests, rose-tinted glasses[*].

I don’t think there is a “better” competitor, except in limited senses: Solaris/IllumOS and OpenBSD both have good-quality code but are not great to use out of the box: Solaris in particular I associate with abysmal package management and flaky support from supposedly cross-platform applications that are actually only ever built and tested on GNU Debian has well-adhered free software guidelines and much better compatibility but not all GNU code is as high-quality as some alternatives. The OpenBSD copyright policy and the FSF definition of freedom are incompatible so OpenBSD doesn’t contain much GNU software GNU doesn’t contain much OpenBSD software: you get a base system that’s either one or the other and have to do work if you want bits of both. Other GNU/Linux distributions can be easier to set up and have better (i.e. any) support for non-free software and wider collections of device drivers.

So there are plenty of alternatives, many of which are good in some ways and bad in others, and all I know is that I don’t want things to be like this, without being able to say I want one of those instead. I don’t even think there will be one of those, at least not in the sense of a competitor to Apple on laptop operating systems. Why not? Because I agree with the following statement from wesolows:

from the perspective of someone who appreciates downstack problems and the value created by solving them, is that the de facto standard technology stack is ossifying upward. As one looks at each progressively lower layer, the industry’s collective willingness to contemplate, much less sponsor, work at that layer diminishes.

There’s still research in operating systems, sure, but is there development? Where are the NeXTs and Bes of today? I don’t believe you could get to a million users and have a Silicon Valley “exit” with low-level technology improvements, and so I don’t think the startup world is working in that area. So we probably won’t get anything good from there. I don’t see competition in operating systems being fruitful. If it were, Sun wouldn’t have been sold.

In fact I don’t even think that Apple’s systems are bad, they’ve just lost the “it just works” sheen. It’s just that when you combine that with the lack of credible alternative, you realise the problem is probably in expecting some corporation to put loads of resources into something that’s not going to have a great value, and merely needs to be “good enough” to avoid having any strategic penalty.

To me, that means treating the low-level parts of the technology stack as a public good. If we accept that the stack is ossifying upwards, and that EM64T, Unix, C, IP, HTTP, SQL and other basic components are going to be around essentially forever[**] then we need to treat them and their implementations as public goods and take common ownership of them. They might not be the best possible, but they are the best available. We (we the people who make systems on top of them, in addition to we the people who use systems made on top of them) need them to work collectively, so we should maintain them collectively.

[*]I particularly like his use of the phrase “Apple-like” in this context, because that term is often used to mean “my platonic ideal of Apple’s behaviour” rather than “what Apple actually does” and reminds me to be wary of my own recollections. I remember Lightning connectors being welcomed in a tweet that derided the old iPod 30-pin connector as “un-Apple-like”, despite the evidence that Apple invented, introduced the 30-pin connector and then supported it for over a decade.

[**] speaking of Sun, I use the definition of computer-forever I learned from a Sun engineer: five years or longer.

On switching to Linux

In November, I switched to GNU/Linux at home (I still use OS X at work, because I still write Objective-C in Xcode at work). Or rather, I switched back: I’d been using it around a decade ago.

The Ubuntu installer on my MacBook air

In December, I resolved to spend more time working with Free Software during 2015 and beyond. Now I find that my story is not unique, others have left OS X (now a dead link, sadly) or are concerned at the state of Apple. I have had conversations with friends about moving from OS X to Debian, to OpenBSD, to other systems.

In my case, there was no watershed moment, no Damascene conversion from the Tablet According to Jobs to the Stallman Doctrine. Rather, my experience has been one of a thousand tiny cuts, and the feeling that while GNU is not actually a better system, it’s one that I’m allowed to make changes to. When iWork was ‘upgraded’ to a less-capable version with an incompatible file format, cut. Every time I plug my Apple display into my Apple computer, then have to unplug it and connect it again before it works properly, cut. Even when the display works, I have to unplug the (Apple) keyboard and plug it back in, cut. Every time iTunes connects to the network but doesn’t let me play any of my tunes, cut. When Apple trumpets the superiority of their new map that shows I live in “Royal Spa”, cut. When iCloud showed its message that I have to upgrade to the new way and devices still on the old way can’t see my files any more, cut. Like the above-linked authors, I’ve got to a point where the only Apple-supplied software in my Dock is the Finder. In my case, it’s happened one app at a time.

The thing is, Apple’s been building some great new things. There’s the watch, Swift, improvements to Cocoa, and they still have the best hardware around. If it weren’t for both the real regressions and the fear of potential regressions on every upgrade or app update, I’d still be confident that their Unix desktop were the best. As it is, I think it could possibly be the least worst, but I’m no longer certain.

Most of the time I don’t care about my computer’s operating environment. This isn’t so much the year of Desktop Linux for me, as the year of Desktop Ambivalence. The OS is the thing that spends most of the time and RAM involved in showing me an emacs window, or a terminal emulator, or a Smalltalk machine, or a web browser. I shouldn’t need to care how it works. But if it’s going to get in my way, give me a chance to do something about it.

The standard trope response is “LOL you must have a bad idea of UX if you use Linux”, which is the sort of thing that was true at the turn of the millennium when most of us were last tyre-kicking some GNU distro but is now an outdated view of the world. But again, should there be a problem, I hope to have the ability to fix it both for myself and others.

So far this year I’ve started small. I’ve been reminding myself of the differences between OS X and BSD commands that I’m used to, and the Linux and SysV commands that I’ve not used frequently in nearly a decade. I’ve been learning about Vala and GTK+.