02 Jun 2026
Planet Grep
Mattias Geniar: More time to think
I'm finding myself thinking longer about the code I write and the features that get developed, than I did before the agentic coding era.
02 Jun 2026 2:40pm GMT
Lionel Dricot: Qucocoma Philippe Samyn ?

Qucocoma Philippe Samyn ?
J'apprends avec tristesse le décès de l'architecte Philippe Samyn, un esprit incroyable aux idées fulgurantes avec qui j'ai eu de longues et passionnantes discussions.
Car l'architecture était pour lui une porte d'entrée vers une compréhension plus globale du monde. Comme lorsqu'il m'a asséné :
- Le monde entier ne tourne qu'autour d'une seule et unique unité, qui est le cœur de tout.
- Euh, le dollar ?
- Tu me déçois Lionel ! C'est le joule bien entendu. Tout tourne autour du joule. Produire, stocker, échanger des joules. La monnaie internationale devrait être le joule ! Les puissants sont ceux qui exploitent la différence entre le dollar et le joule, les faibles ceux qui fournissent des joules pour rien ou si peu.
Ou cette discussion qui me revient régulièrement où il m'exposa que l'architecte devait construire des « ruines utiles ». Car un bâtiment ne va être utilisé que 50, 100 ou 300 ans. Mais ses ruines durent parfois 10 ou 100 fois plus longtemps. Certaines ruines dureront autant que la planète ! L'essentiel de la vie d'un bâtiment se fait à l'état de ruine et il faut le prévoir dès la conception.
Avant de le rencontrer, je n'avais jamais envisagé les choses sous cet angle. Ce qui m'a frappé en généralisant son discours, c'est à quel point le fait de tenter d'oublier l'étape des ruines est la maladie qui pourrit l'humanité tout entière à tous les niveaux.
Nous produisons, nous tentons de produire plus et plus rapidement sans jamais nous préoccuper de ce que nous allons faire de toute cette production. Nous en sommes au point d'automatiser la production d'images, d'écrits et de code informatique avec les chatbots sans nous poser la question des ruines que nous préparons.
Depuis plusieurs années, chaque fois que j'ai envie de me procurer un bien matériel, je me pose consciemment deux questions : « Où vais-je le ranger ? » et « Comment vais-je m'en débarrasser ? ». Penser consciemment à cette question au moment de l'achat rend l'achat en lui-même extrêmement anxiogène. Philippe Samyn avait lui poussé cette réflexion jusque dans la conception des bâtiments.
Mais l'ingénieur architecte était également un artiste attaché à son œuvre. Lorsque mon épouse et moi avons un jour critiqué « son » Aula Magna, bâtiment emblématique de Louvain-La-Neuve coincé entre un cinéma et un hôtel, il nous a déroulé, des larmes pleins les yeux, le plan de Louvain-la-Neuve tel qu'il l'avait imaginé et comment l'Aula Magna aurait du s'intégrer dans une superbe perspective bien plus vaste et cohérente. Une boule de colère et de tristesse dans la gorge, il nous a expliqué comment son projet avait été complètement dénaturé en n'en prenant qu'une partie et en l'encadrant d'autres immeubles qu'il trouvait hideux.
Philippe Samyn m'avait fait l'honneur de me compter parmi les bêta-lecteurs de l'œuvre de sa vie : un ouvrage exhaustif sur l'architecture et la société humaine, projet qu'il avait intitulé: « Qucocoma, Quoi Comment Construire Maintenant ».
Je lui avais prédit que cette œuvre risquait de ne jamais être achevée tant elle était ambitieuse, qu'il fallait absolument la publier par petite partie sous peine de laisser cette tâche à ses héritiers.
Je ne pensais pas avoir raison si tôt…
Philippe Samyn s'est éteint, mais le territoire reste à jamais marqué par ses idées.
À propos de l'auteur :
Je suis Ploum et je viens de publier Bikepunk, une fable écolo-cycliste entièrement tapée sur une machine à écrire mécanique. Pour me soutenir, achetez mes livres (si possible chez votre libraire) !
Recevez directement par mail mes écrits en français et en anglais. Votre adresse ne sera jamais partagée. Vous pouvez également utiliser mon flux RSS francophone ou le flux RSS complet.
02 Jun 2026 2:40pm GMT
Dries Buytaert: Contentful and the limits of "Buy European"
This morning, Salesforce announced its plan to acquire Contentful.
Congratulations to Sascha Konietzke, Paolo Negri, and the whole Contentful team. They spent 13 years building Contentful into one of Europe's most visible enterprise software companies. Salesforce buying Contentful is real validation of the product, customers, and team they built.
The deal makes sense for both Salesforce and Contentful. Salesforce has long had a CMS-shaped hole in its product offering, and Contentful fills it with a mature, enterprise-ready SaaS product.
Contentful last raised money in 2021, at a valuation of more than $3 billion, when SaaS valuations were near their peak and enthusiasm for headless CMS was at its highest. Since then, valuations have come down, and developers have become more pragmatic about when a headless CMS makes sense.
To me, the more important question isn't whether the acquisition makes strategic sense (it does), or whether every Contentful investor got the outcome they hoped for (probably not). It is what the acquisition means for digital sovereignty.
Before I go further, let me be clear about where I'm coming from. I founded Drupal and still lead the project, and I co-founded Acquia, a company built around Drupal, where I'm still the Executive Chair. Drupal is an Open Source CMS that competes with Contentful. So when I argue that this deal raises important questions, you should factor in that Open Source is both my life's work and my livelihood.
Contentful is a German company, Contentful GmbH, registered in Berlin. For over a decade it has been a flagship European software company.
If the acquisition closes, it becomes part of Salesforce, a US corporation, and falls under US law.
For many of Contentful's customers, this acquisition will be a non-event. For governments, public institutions, and regulated industries, it exposes a harder truth: a vendor being European today is no guarantee it stays European tomorrow.
A practical example is the US CLOUD Act. Many people may not know about it, but it becomes relevant anytime a non-US vendor is acquired by a US company.
In plain English, the CLOUD Act means that US authorities can require any US company to disclose data it controls. That can apply even if its data is stored in Europe, managed by a European team, or running on European infrastructure.
This is not a hypothetical concern. The law came out of a dispute between Microsoft and the US government over emails stored in Ireland. US Congress changed the law while the case was pending, making clear that US providers can be required to produce data stored abroad.
That does not make Contentful a bad company. It does not make Salesforce a bad owner. And it does not take anything away from what the Contentful team built.
But it shows the limit of "Buy European". Contentful spent 13 years as a trusted European vendor, and one board meeting is enough to put it under US law.
That is where Open Source matters. Drupal customers running on Acquia, my own US-based company, are also exposed to US law. But because Drupal is Open Source, they have alternatives: they can move to a European hosting partner, self-host, or fork the code. A Contentful customer cannot do the same.
The Contentful team deserves credit for what they built. Few European software companies have reached its scale and size. But this is also a reminder for Europe. For software that governments, public institutions, and critical industries depend on, sovereignty must survive any acquisition.
That is the point of The Software Sovereignty Scale and The Sovereignty Prerequisite that I submitted to the European Commission as feedback on their Cloud Sovereignty Framework.
Open Source is the only way to guarantee long-term choice, control, and governance over your code, data, and infrastructure.
Special thanks to Tiffany Farriss for her review of this blog post.
02 Jun 2026 2:40pm GMT
Planet Debian
Ben Hutchings: FOSS activity in 2025

This was a particularly busy month for me in terms of Debian contributions.
It started with a week in Hamburg for the MiniDebConf. I talked to many colleagues face-to-face and worked on various bugs and maintenance tasks. I'm pleased to have finally found the time to reproduce and fix the boot-time crashes in the parallel port subsystem that have been reported many times recently.
A series of easily exploited kernel LPE (local privilege execution) issues were published this month, mostly with very little coordination with distributions. Salvatore and I had to upload fixes for these at roughly weekly intervals. All of these fixes needed to be applied to 4 different upstream branches (currently 5.10, 6.1, 6.12, and 7.0) and 7 Debian branches (including backports).
- Debian packages:
- cis-tools:
- dracut:
- Bugs:
- replied to #1131809: dracut: ppc64el autopkgtest are flaky and take 7 hours per run (and discussed it in-person in Hamburg)
- Bugs:
- firmware-free:
- Bugs:
- Merge requests:
- firmware-nonfree:
- Merge requests:
- closed !68: Draft: Update bullseye in line with buster
- reviewed and merged !146: gencontrol: s/initramfs-tools/update-initramfs/
- merged !147: control: stop suggesting initramfs-tools
- opened and merged !148: Update to 20260519
- opened and merged !149: Include more firmware in binary packages
- opened !150: Update and remove obsolete package relations
- Merge requests:
- gnome-shell:
- Bugs:
- replied to and reassigned #1135951: linux-image-6.12.85+deb13-amd64: secure data is visible when waking from suspsend
- Bugs:
- initramfs-tools:
- Bugs:
- Merge requests:
- reviewed !142: Handle simple-framebuffer drivers and framebuffer_coreboot built as modules
- closed !150: Do not install ARM/RISCV specific modules on other architectures
- closed !173: Draft: Introduce copy_file helper program to replace copy_file function
- opened and merged !195: unmkinitramfs: Make it compatible with Busybox cpio
- reviewed !196: add module to add fw files from DT firmware-name properties
- Uploads:
- uploaded version 0.148.4 to trixie
- ktls-utils:
- Merge requests:
- merged !5: Update to 1.4.0
- Uploads:
- uploaded version 1.4.0-1 to unstable
- Merge requests:
- linux:
- Bugs:
- replied to #1130365: linux-image-6.18.15+deb14-amd64: kernel panic during startup
- replied to #1136800: linux-image-7.0.4+deb14-amd64: fails to boot
- replied to #1136894: linux-image-7.0.4+deb14-amd64: Kernel Panic - AMDGPU crash
- replied to #1136978: linux-image-7.0.4+deb14-amd64: kernel NULL pointer dereference
- replied to and closed #1137202: linux-image-7.1-amd64: Kernel panic on boot
- replied to #1137203: bnx2: ifupdown-hotplug fails at boot, no network, regression from 5.10.0-42
- replied to #1137642: linux-image-7.0.7+deb13-amd64: Failed to load Bluetooth driver
- Merge requests:
- closed !1720: arm64: Enable Renesas RZ/G2L features
- merged !1759: [arm64] Enable AIR_EN8811H_PHY as module
- merged !1792: [arm64] Enable BST platform support
- closed !1817: [sparc64] Add patches to fix user stack sync and add clone3() syscall
- merged !1837: [arm64] Enable configs for Qualcomm RB1 boards
- reviewed !1845: [amd64,arm64] Enable KEXEC_HANDOVER and LIVEUPDATE
- merged !1878: [riscv64] Enable CMA and DMA_CMA. Set CMA_SIZE_MBYTES=64
- merged !1884: [amd64] Enable Intel USBIO bridge driver and submodules
- opened !1904: Improve package descriptions for most of the kernel packages
- reviewed and merged !1906: Enable SND_SOC_SDCA_CLASS and SND_SOC_SDCA_{FDL, HID, IRQ} for Panther Lake audio support
- opened and merged !1910: Add backported patches for Dirty Frag attack
- merged !1911: Qualcomm Monaco and Talos support
- merged !1913: d/watch: migrate to version 5
- reviewed !1936: [sparc64] Add nvme module to scsi-modules udeb
- reviewed !1948: [amd64] Enable Intel Platform Hardware Support Drivers
- opened and merged !1951: Fix dirtying of the source tree when building tools
- merged !1954: 7.0 backport 'Fix for "fragnesia" (CVE-2026-46300) and variants'
- merged !1955: 6.12 backport 'Fix for "fragnesia" (CVE-2026-46300) and variants'
- opened !1956: Draft: Enable a fully parallel build
- Uploads:
- (LTS) uploaded versions 5.10.251-2, 5.10.251-3, 5.10.251-4, 5.10.251-5, 5.10.257-1 to bullseye-security
- uploaded versions 6.12.85-1~bpo12+1, 6.12.86-1~bpo12+1, 6.12.88-1~bpo12+1, 6.12.90-1~bpo12+1, 6.12.90-2~bpo12+1 to bookworm-backports
- uploaded versions 6.19.14-1~bpo13+1, 7.0.10-1~bpo13+1, 7.0.4-1~bpo13+1, 7.0.7-1~bpo13+1, 7.0.9-1~bpo13+1 to trixie-backports
- Bugs:
- (LTS) linux-6.1:
- Uploads:
- uploaded versions 6.1.170-1~deb11u1, 6.1.170-3~deb11u1, 6.1.172-1~deb11u1, 6.1.174-1~deb11u1 to bullseye-security
- Uploads:
- miniramfs:
- Bugs:
- replied to #1132532: miniramfs: Missing cpio dependency
- Bugs:
- nfs-utils:
- wireless-regdb:
- Uploads:
- uploaded version 2026.03.18-1 to unstable
- Uploads:
- Debian non-package bugs:
- Mailing lists:
- debian-boot:
- debian-devel:
- replied to Licensing of licenses
- debian-kernel:
- posted Agenda items for kernel-team meeting on 2026-05-13
- posted and replied to [RFC] Using SimpleDRM in the initramfs
- replied to [bjarniig@simnet.is: kernel-img.conf.5: warning from "lint"]
- debian-lts-announce:
- posted [SECURITY] [DLA 4560-1] linux security update
- posted [SECURITY] [DLA 4561-1] linux-6.1 security update
- posted [SECURITY] [DLA 4572-1] linux security update
- posted [SECURITY] [DLA 4574-1] linux-6.1 security update
- posted [SECURITY] [DLA 4587-1] linux security update
- posted [SECURITY] [DLA 4588-1] linux-6.1 security update
- posted [SECURITY] [DLA 4606-1] linux security update
- posted [SECURITY] [DLA 4607-1] linux-6.1 security update
- linux-hyperv:
- linux-perf-users:
- posted and replied to [PATCH 0/3] Fix out-of-tree build of some tools
- linux-sh:
- linux-trace-kernel:
- netdev:
- (mostly LTS) stable:
- replied to Linux 5.15.205
- posted [5.10,5.15] i3c: fix uninitialized variable use in i2c setup
- posted [6.6] fbdev/vt8500lcdfb: Initialize fb_ops with fbdev macros
- posted [6.6] net: skbuff: propagate shared-frag marker through frag-transfer helpers
- posted [6.6] x86/CPU/AMD: Move the Zen3 BTC_NO detection to the Zen3 init function
- posted [7.0] perf loongarch: Fix build failure with CONFIG_LIBDW_DWARF_UNWIND
- replied to [PATCH 5.10 002/589] ASoC: SOF: topology: reject invalid vendor array size in token parser
- replied to [PATCH 5.10 027/589] xfrm: Wait for RCU readers during policy netns exit
- replied to [PATCH 5.10 072/589] media: uvcvideo: Use heuristic to find stream entity
- replied to [PATCH 5.10 095/589] ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
- replied to [PATCH 5.10 096/589] scsi: ufs: core: Improve SCSI abort handling
- posted [PATCH 5.10 1/2] Revert "RDMA/rxe: Fix double free in rxe_srq_from_init"
- replied to [PATCH 5.10 101/589] rxrpc: Fix key quota calculation for multitoken keys
- replied to [PATCH 5.10 114/589] arm64: dts: imx8mq-librem5: Dont mark buck3 as always on
- replied to [PATCH 5.10 176/589] KVM: nSVM: Mark all of vmcb02 dirty when restoring nested state
- replied to [PATCH 5.10 177/589] KVM: nSVM: Sync NextRIP to cached vmcb12 after VMRUN of L2
- posted and replied to [PATCH 5.10 2/2] RDMA/rxe: Fix double free in rxe_srq_from_init
- posted [PATCH 5.10-5.15] apparmor: validate default DFA states are in bounds
- posted [PATCH 5.10-6.1] fbdev: vt8500lcdfb: Fix dma_free_coherent() cpu_addr parameter
- posted [PATCH 5.10-6.1] x86/CPU/AMD: Move the Zen3 BTC_NO detection to the Zen3 init function
- replied to [PATCH 5.10] Revert "s390/cio: Fix device lifecycle handling in css_alloc_subchannel()"
- posted [PATCH 5.10] Revert "s390/cio: Fix device lifecycle handling in css_alloc_subchannel()"
- posted [PATCH 5.10] net: skbuff: preserve shared-frag marker during coalescing
- posted [PATCH 5.10] net: skbuff: propagate shared-frag marker through frag-transfer helpers
- posted [PATCH 5.10] phy: renesas: rcar-gen3-usb2: Fix msleep() in atomic context
- posted [PATCH 5.10] selftests: forwarding: lib: Add helpers for checksum handling
- posted [PATCH 5.15 1/2] Revert "RDMA/rxe: Fix double free in rxe_srq_from_init"
- posted [PATCH 5.15 2/2] RDMA/rxe: Fix double free in rxe_srq_from_init
- replied to [PATCH 5.15.y] net: usb: lan78xx: Fix double free issue with interrupt buffer allocation
- posted [PATCH 5.15] net: skbuff: propagate shared-frag marker through frag-transfer helpers
- posted [PATCH 5.15] selftests: forwarding: lib: Add helpers for checksum handling
- posted [PATCH 6.1 1/2] Revert "RDMA/rxe: Fix double free in rxe_srq_from_init"
- posted [PATCH 6.1 2/2] RDMA/rxe: Fix double free in rxe_srq_from_init
- posted [PATCH 6.1] apparmor: validate default DFA states are in bounds
- posted [PATCH 6.1] net: skbuff: propagate shared-frag marker through frag-transfer helpers
- posted [PATCH 6.1] selftests: forwarding: lib: Add helpers for checksum handling
- posted [PATCH 6.6] net: skbuff: propagate shared-frag marker through frag-transfer helpers
- replied to [PATCH net] net: skbuff: propagate shared-frag marker through pskb_copy()
- posted [PATCH] parport: Fix race between port and client registration
02 Jun 2026 2:17pm GMT
01 Jun 2026
Planet Lisp
Joe Marshall: Regression
Last year I wrote some Lisp related AI apps. There was a syntax highlighter that used the LLM to determine how to colorize and highlight syntax, and a prompt refiner that takes a wimpy LLM prompt and creates more elaborate prompt from them.
I took the apps down last week. They were `vibe coded' and therefore approximate and had bugs (but that's to be expected), but they had a security hole where you could hijack the LLM processing with your own prompt turning my app into an open relay using my API key. Last week I discovered that my AI spend on video creation was becoming serious. This is odd because I never create AI video. It turned out that my app was being hijacked by a proxy in Luxembourg and was generating videos on my dime.
So I shut down the apps. I knew they had the potential of being abused, and I was willing to tolerate a small amount of abuse, but it didn't occur to me that syntax highlighter could be hijacked to generate gigabytes of video at my expense. Future applications will be careful to obtain the API key from the user.
01 Jun 2026 7:00am GMT
Planet Debian
Amin Bandali: Free software activities in May 2026
Hello and welcome to my May 2026 free software activities report. A lot's been going on in my life offline so I took a bit of a hiatus from doing these reports, but I've had a fairly productive month of May so I thought it'd be nice to do another one for this month.
GNU & FSF
- GNU Emacs:
- ffs-0.2.2: I finally polished and published my
ffspackage for GNU Emacs on GNU ELPA. Many thanks to Protesilaos for rounds of code review and feedback for improving and polishing the package in preparation for submission to GNU ELPA. - bug#81101: Trying to visit https://www.emacswiki.org in EWW I noticed it fails with a
Somebody wants you to give them moneyerror due to the anti-bot challenge being served with a HTTP 402 (Payment Required) response. So I landed a patch12eec781ed6to no longer do that. Thanks to Emacs comaintainer Sean Whitton for reviewing and approving my proposed patch. - bug#81107: I noticed that in EWW, unlike
<input type="submit">HTML buttons,<button>elements were not tab-stoppable, leading to poorer usability and accessibility. So I landed a patchec3d662de0bto fix that. Thanks to Emacs comaintainer Eli Zaretskii for reviewing, providing feedback, and accepting my proposed change. - Emacs Chat with Sacha Chua: I joined Sacha for a new episode of her Emacs Chat podcast, where we talked about Emacs and life. I gave a quick tour of my Emacs configuration, discussing at length my configurations for EXWM (Emacs X Window Manager) among other topics like Emacs's facility for visually indicating buffer boundaries in the fringe by setting
indicate-buffer-boundariesand my convenience configuration macros.
- ffs-0.2.2: I finally polished and published my
- maintainers@: I started the next long-overdue round of emails to GNU package maintainers to confirm the contact information we have on file for them and get a brief status update about their packages. Emails are sent in small batches to keep the workload of handling the responses manageable for assistant GNUisances.
- GNU Spotlight: I prepared and sent the May GNU Spotlight to the FSF campaigns team for publication on the FSF's community blog and the monthly Free Software Supporter newsletter.
Debian
I've begun the work toward updating the Jami package in Debian unstable again, which means I need to package new releases of its direct and indirect dependencies. For OpenDHT, I need to update RESTinio, and to do that I first need to package expected-lite and sobjectizer for Debian:
- #1120837: ITP: expected-lite - expected objects for C++11 and later
- #1137609: ITP: sobjectizer - C++ implementation of Actor, Publish-Subscribe, and CSP models
I've been working on packaging both and hope to have them uploaded to the archive in the next days and weeks.
That's it for this month's report.
Take care, and so long for now.
01 Jun 2026 2:30am GMT
31 May 2026
Planet Debian
Russell Coker: Links May 2026
Ron Garrett wrote an interesting blog post about the mathematical possibility of abiogenesis [1].
The Register has an informative article about the threat that management systems built in to Intel and AMD CPUs pose to data sovereignty in EU owned cloud providers [4]. But this is just the first stage of building sovereign clouds, all significaant cloud services run at least 2 types of CPU and adding EU manufactured CPUs at a future time will be easy.
Michael Prokop wrote an interesting blog post about debugging input event problems on Linux which turned out to be due to an analogue headphone connection [8]. This gave me some useful pointers to investigating an input device problem which is probably very different.
Tianon Gravi wrote an informative blog post about containers, Debian, and Docker options [12]. We need a lot more work on these sorts of things in Debian.
- [1] https://tinyurl.com/25p5w844
- [2] https://pluralistic.net/2026/04/20/praxis/#acceleration
- [3] https://tinyurl.com/2az3uazq
- [4] https://tinyurl.com/26aygdv6
- [5] https://www.youtube.com/watch?v=_bP80DEAbuo
- [6] https://tinyurl.com/yvnszuyh
- [7] https://tinyurl.com/ymmcpt9t
- [8] https://tinyurl.com/2859uflr
- [9] https://www.youtube.com/watch?v=IHD8BDFYyGI
- [10] https://anarc.at/blog/2026-05-16-four-horsemen/
- [11] https://tinyurl.com/26mhk6ok
- [12] https://tinyurl.com/2dba3jut
- [13] https://arxiv.org/pdf/1802.09517
- [14] https://tinyurl.com/2cfo3nsa
31 May 2026 12:08pm GMT
Planet Lisp
Joe Marshall: CLRHack: Meta-object Protocol
Metaobject Protocol (MOP) Implementation in CLRHack
The Metaobject Protocol in CLRHack is a high-performance implementation of the Common Lisp Object System (CLOS) integrated into the .NET 8.0 Common Language Runtime (CLR). It provides a complete meta-compilation pipeline that bridges the gap between dynamic Lisp semantics and the static CIL (Common Intermediate Language) execution model.
Core Architecture
The MOP is implemented through three primary layers:
- The Metaobject Hierarchy (C#): A set of foundational classes in
LispBaserepresenting classes, methods, generic functions, and slot definitions. - The Runtime Engine (
MopRuntime): A centralized orchestrator that manages class finalization, method combination, dispatch caching, and instance allocation. - The Compiler Bridge (Lisp): Transformations in
ast.lispthat translate high-level CLOS forms (defclass,defmethod) into optimized runtime calls.
Instance Representation
Because the CLR type system is strictly single-inheritance and statically defined, CLRHack decouples Lisp-level inheritance from C# inheritance. All CLOS instances are represented by the StandardObjectInstance class, which contains:
- A reference to its
ClassMetaobject. - A private
object[] storagearray for instance slots, indexed by locations calculated during class finalization.
The Dispatch Pipeline
Generic function invocation is the most complex part of the implementation. When a generic function is called:
- Cache Lookup: The
DiscriminatingFunctionfirst checks a thread-safedispatchCacheusing anInvocationCacheKey(a stack-allocatedstruct) to find a previously computed effective method. - Applicability & Precedence: If the cache misses, the runtime computes all applicable methods and sorts them based on specializer specificity and the Class Precedence List (CPL).
- Method Combination: The
ComputeEffectiveMethodlogic builds a nested execution chain following the Standard Method Combination rules::aroundmethods are called first, withcall-next-methodprogressing to the next around method or the main chain.- The main chain executes all
:beforemethods, the primary method, and finally all:aftermethods in reverse order.
- Fast Invocation: The resulting effective method is compiled into a
Func<object[], object>that uses direct delegate invocation to minimize overhead.
Challenges and Solutions
1. Thread-Safe Non-Local Exits (call-next-method)
Challenge: call-next-method and next-method-p require access to the current invocation's state (the remaining methods and original arguments). Passing this state through every function call would break compatibility with standard Lisp function signatures.
Solution: CLRHack utilizes [ThreadStatic] fields in MopRuntime to store the currentNextMethods and currentArguments. This ensures that even in highly concurrent environments (like a web server), each OS thread has its own isolated invocation context, allowing call-next-method to function correctly without state leakage.
2. Forward References and Lazy Finalization
Challenge: Lisp allows classes to refer to superclasses that haven't been defined yet. The runtime must handle these "zombie" classes without crashing the JIT compiler.
Solution: The system implements a ForwardReferencedClassMetaobject. When a class is defined, it is automatically finalized (computing its CPL and slot layout). If a superclass is missing, a forward reference is created. The EnsureFinalized protocol ensures that inheritance is resolved and slot locations are assigned the moment the class is first instantiated or used in dispatch.
3. Performance Overhead of the "MOP Bridge"
Challenge: A naive implementation of slot-value or generic dispatch using C# reflection or linear searches is orders of magnitude slower than native C# member access.
Solution: Three distinct optimizations were applied:
- O(1) Slot Access: Each
ClassMetaobjectmaintains aSlotDictionary. Slot names are mapped to physical array indices during finalization, allowingslot-valueto perform a direct array access after a single dictionary lookup. - Compiler Primitives: The compiler identifies
SLOT-VALUEandMAKE-INSTANCEcalls and emits direct CILcallinstructions to optimizedLisp.MopRuntimemethods, bypassing the generalFuncallpath. - Zero-Allocation Cache Hits: By making
InvocationCacheKeyareadonly structand avoiding the cloning of the argument array during cache probes, the hot-path for generic function dispatch generates zero garbage for the .NET Collector.
4. Bootstrapping the COMMON-LISP Package
Challenge: Core CLOS functions like make-instance must be available as symbols in the COMMON-LISP package before user code runs, but they rely on the MOP runtime being fully initialized.
Solution: A MopRuntime.Initialize() method is injected into the entry point (Main) of every generated assembly. This method interns the necessary symbols and binds them to GenericFunctionClosureAdapter objects, ensuring that the MOP is "alive" before the first line of Lisp code executes.
Vibe coding the MOP basically involved feeding chapters 4 and 5 of the Art of the Meta-Object Protocol into the LLM and telling it to make an implementation plan. It came up with a twenty-step plan to bootstrap CLOS. I then spent the rest of the day instructing an agent to take on each task of the twenty-step plan in sequential order. At the end of the day, I had a working MOP
This is the end of my series of posts on CLRHack.
31 May 2026 7:00am GMT
30 May 2026
Planet Lisp
Joe Marshall: CLRHack: signal and error
Implementation of SIGNAL and ERROR in CLRHack
In CLRHack, the condition signaling system is implemented in the Lisp.HandlerControl class within the LispBase library. It leverages .NET's [ThreadStatic] storage to maintain a per-thread dynamic stack of active condition handlers.
SIGNAL Implementation
The Signal(object condition) method performs the following logic:
- Retrieval: It fetches the
activeHandlerslist for the current thread. This list is a chain of[LispBase]Lisp.Handlerobjects maintained byhandler-bind. - Iteration: It iterates linearly through the list from the most recently bound handler to the oldest.
- Type Matching: For each handler, it calls
IsType(condition, handler.ConditionType).- If the condition is a symbol, it checks for symbol equality (supporting simple symbol-based conditions).
- If the condition is a .NET object, it checks if the handler's type is assignable from the condition's runtime type (supporting interop with system exceptions).
- It treats the symbols
TorEXCEPTIONas catch-all types.
- Handler Invocation: If a match is found:
- Recursive Signal Protection: Before calling the handler function, the current handler list is temporarily shadowed.
activeHandlersis set tocell.rest(the handlers bound outside the current one). This ensures that if the handler itself callssignal, it won't trigger itself recursively. - Execution: The handler's
Closureis invoked with the condition object as its argument. - Restoration: A
finallyblock ensures the originalactiveHandlerslist is restored if the handler returns normally.
ERROR Implementation
The
Error(object condition)method build uponSignal:- Signaling Pass: It first invokes
Signal(condition). If a handler performs a non-local exit (e.g., viahandler-case), theErrormethod never returns. - Debugger Entry: If
Signalreturns normally (meaning all handlers declined),ErrorcallsEnterDebugger(condition). - Interactive Debugging: The debugger:
- Prints the condition and a list of available restarts (retrieved via
RestartControl.GetActiveRestarts()). - Provides a prompt for the user to select a restart, launch the system-level debugger (Visual Studio/Rider), or abort.
- If a restart is selected, it is invoked interactively (potentially gathering arguments from the user).
- Prints the condition and a list of available restarts (retrieved via
- Final Fallback: If the debugger is exited without invoking a restart,
Errorthrows a C#Exceptionto ensure that execution does not continue on an invalid path.
Notable Implementation Decisions and Edge Cases
- Recursive Signal Protection: Before calling the handler function, the current handler list is temporarily shadowed.
- Handler Shadowing: The decision to pop the handler list during invocation is critical for maintaining Common Lisp semantics. It prevents infinite loops and ensures that "outer" handlers can handle errors raised within "inner" handlers.
- Unified Exception Model: CLRHack attempts to unify Lisp conditions and .NET exceptions.
IsTypeallows Lisp handlers to catch C# exceptions by their class name or Type object. - Thread Isolation: By using
[ThreadStatic]foractiveHandlers, CLRHack ensures that condition signaling is thread-safe. One thread signaling an error will not interfere with the handler state of another thread. - Debugger Capability: The
SYSTEM-DEBUGGERoption inEnterDebuggeris a bridge to the underlying .NET environment, allowing developers to use professional IDE tools to inspect the state of the Lisp VM when an unhandled error occurs.
signal and error complete the Common Lisp condition system implementation for CLRHack
30 May 2026 7:00am GMT
25 Apr 2026
FOSDEM 2026
All FOSDEM 2026 videos are online
All video recordings from FOSDEM 2026 that are worth publishing have been processed and released. Videos are linked from the individual schedule pages for the talks and the full schedule page. They are also available, organised by room, at video.fosdem.org/2026. While all released videos have been reviewed by a human, it remains possible that one or more issues fell through the cracks. If you notice any problem with a video you care about, please let us know as soon as possible so we can look into it before the video-processing infrastructure is shut down for this edition. To report any舰
25 Apr 2026 10:00pm GMT
29 Jan 2026
FOSDEM 2026
Join the FOSDEM Treasure Hunt!
Are you ready for another challenge? We're excited to host the second yearly edition of our treasure hunt at FOSDEM! Participants must solve five sequential challenges to uncover the final answer. Update: the treasure hunt has been successfully solved by multiple participants, and the main prizes have now been claimed. But the fun doesn't stop here. If you still manage to find the correct final answer and go to Infodesk K, you will receive a small consolation prize as a reward for your effort. If you're still looking for a challenge, the 2025 treasure hunt is still unsolved, so舰
29 Jan 2026 11:00pm GMT
26 Jan 2026
FOSDEM 2026
Call for volunteers
With FOSDEM just a few days away, it is time for us to enlist your help. Every year, an enthusiastic band of volunteers make FOSDEM happen and make it a fun and safe place for all our attendees. We could not do this without you. This year we again need as many hands as possible, especially for heralding during the conference, during the buildup (starting Friday at noon) and teardown (Sunday evening). No need to worry about missing lunch at the weekend, food will be provided. Would you like to be part of the team that makes FOSDEM tick?舰
26 Jan 2026 11:00pm GMT