Skip to content

Add secondary, more detailed version marker and specify TARGET_APPIMAGEΒ #38

@TheAssassin

Description

@TheAssassin

While experimenting with fully static type-2 runtime builds, we found that this breaks AppImageLauncher's integration method which currently depends on LD_PRELOAD. I recently discussed this problem with @probonopd, and we came up with a solution.

Some background: AppImageLauncher depends on binfmt_misc for its core UX feature. All calls to (executable) AppImages are intercepted by AppImageLauncher. Of course, it cannot "just launch" the AppImage any more, resulting in a loop. It needs to bypass binfmt_misc therefore to launch the AppImages after treating them.

To do so, currently, AppImageLauncher extracts the runtime into an in-memory buffer and there, it patches out the magic bytes. This allows it to launch the binary normally while minimizing RAM consumption and avoiding having to copy the entire AppImage to a temporary location. To my own surprise (at least to some extent), this works extremely reliably with the classic upstream AppImageKit type-2 runtime and also the good old type 1 runtime.

Of course, AppImageLauncher needs to tell the runtime where the AppImage really is. This is done by hooking into some of the functions we know it uses that, e.g., open a file handle on the AppImage file on the disk. There, the path can be patched dynamically.

In the past, in the very first versions, TARGET_APPIMAGE even was the main method of telling the runtime which AppImage to launch. Back then AppImageLauncher shipped its own upstream type-2 runtime, which limited the user experience quite a bit. The flag would work with the method described above, though. There are multiple reasons I no longer use it, though. First of all, this feature never made it into the spec, which means that only the upstream runtime can work with it and all other AppImages would crash. We cannot safely assume that all type-2 AppImages provide it. Even if just 10% of the AppImages would be incompatible, they would just crash. The "hook into them with LD_PRELOAD method" is not affected by this limitation. We have no means of distinguishing between those runtimes.

To make the operation more reliable and allow the tool to work with fully static runtimes, I think it would be totally sufficient to just standardize the $TARGET_APPIMAGE feature. All compliant runtimes would need to support it, if it wouldn't work we could make users report that as a bug then. In the same moment, we could explicitly mention that both static and shared builds are permitted.

To communicate that the feature is available, we need to bump the AppImage type/version in some way. In my opinion, it makes no sense to release an entirely new type-3 at this point. What we could do is release a type 2.1 that adds these features. The current magic bytes embedding is not capable of this, though. Therefore, we could pick up the ideas from #26 and add a second(!) more fine grained version marker. This serves two purposes: first, it allows us a "soft start" into actually versioning and releasing the spec, something we have wanted to do for a while already. Second, by adding some "minor" version number (or even going full semver), tools like AppImageLauncher can reliably detect such new features like $TARGET_APPIMAGE. Third, by adding the version marker as a second feature, all tools that currently rely on the type-2 MIME type (or otherwise use the magic bytes) will continue to work. After all, we just add new features, but the type itself is the same and everything will continue to work. Only tools that need new features need to check for the new marker as well. Third, this serves as a test bed for the new proposed type-3 version marker that will replace the magic bytes at offset 0x8 in the long term to improve compatibility with various loaders.

TL;DR: let's add $TARGET_APPIMAGE and a new, secondary AppImage type marker to the specification.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions