The many layers to launch a game

Starting with proton 5.13 steam always launches games inside a sort of container prepared by pressure-vessel (a sort of fork from flatpak). This container is called a ‘steam runtime’ : an introduction talk to runtimes.

digraph {
  rankdir=BT
  node [shape=box]
  subgraph cluster_host {
    label="Host System"
    color=green
    style=dashed
    othr_lib [label="Other system libs"]
    grap_lib [label="Graphical stack libs"]
    runt_tar [
      fontcolor=blue
      href=":https://repo.steampowered.com/steamrt-images-soldier/snapshots/" target=_parent
      label="Runtime tarball"]
  }
  subgraph cluster_runtime {
    label="Steam runtime (soldier)"
    color=green
    style=dashed
    link_lib [label="Symlinks to graphical stack"]
    runt_lib [label="Runtime libs\n(replaces native libs)"]
  }
  subgraph cluster_wine {
    label="Wine runtime"
    color=green
    style=dashed
    emul_dir [label="WINEPREFIX\n(emulated windows folder\nhierarchy)"]
    emul_lib [label="Wine re-implementation\nof windows libs"]
    real_lib [label="Windows real libs\n(.net, ucrtbase c++ runtime)"]
    prot_lib [label="Proton libs\n(not sure what is\nadditional to wine)"]
    game_bin [color=red penwidth=2
      label="Windows native game binaries"]
  }
  pres_ves [label="pressure-vessel"]
  bwrp_bin [label="Bubblewrap\n(util to create containers\nno root privilege needed)"]
  note_real_lib [color=grey
    fontcolor=blue
    href="https://github.com/Winetricks/winetricks" target=_parent
    label="Can be installed by winetricks.\nNot included in wine\nby default"]
  note_prot_lib [color=grey
    fontcolor=blue
    href="https://github.com/ValveSoftware/Proton/blob/proton_5.13/proton" target=_parent
    label="Can be configured via user_settings.py"]

  runt_tar -> pres_ves -> bwrp_bin
  bwrp_bin -> {link_lib runt_lib}
  grap_lib -> link_lib [arrowhead=none]
  {emul_lib real_lib prot_lib} -> emul_dir
  emul_dir -> game_bin

  prot_lib -> note_prot_lib [arrowhead=none color=grey]
  real_lib -> note_real_lib [arrowhead=none color=grey]

  note_prot_lib -> note_real_lib [style=invis]
  runt_lib -> prot_lib [style=invis]
}

Some problemos while running games

There are several families of errors: problems setting up the steam runtime, missing functionality on the wine libs reimplementations, or plain old crashes of binaries.

The fcntl ADD_SEALS problemo

This broke the very start of pressure-vessel runtime init.

The flatpak code inside pressure-vessel has some routines to put stuff into “anonymous tmpfs files”. It then calls fcntl(ADD_SEALS) to prevent the contents from being modified. It looks like this snippet.

void buffer_to_sealed_memfd_or_tmpfile (const char  *name,
                                        const char  *content,
                                        size_t      len) {
  int memfd = memfd_create (name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
  ftruncate (memfd, len);
  write (memfd, content, len);
  lseek (memfd, 0, SEEK_SET);
  errno = 0;
  fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
  perror("fcntl result: ");
}

fcntl(ADD_SEALS) fails with EBUSY if the memory of the file has any direct mapping. Not sure why, but this is always the case when THP for shmem is “always” enbaled.

Network drop problemo

Broke AOE2 multiplayer.

Wine reimplementation of the c++ runtine is not perfect. For some games it is better to use the real deal.

Pagefault problemo

Likely cause of game freezes on AOE2 ? Note some read page fault seem benign.

Randomly, after about 20mins of gameplay, the game would freeze with :

Unhandled exception: page fault on execute access to 0x054fb120

Seems solved with the release of proton 5.13.

Some steam kung-fu to debug game issues

Controlling wine logging via user_settings.py

WARNING: Each version of proton has its one copy of user_settings.py

With a bit of python coding you can choose some proton and wine options for each game launched based on its numerical steam id. See this doc to know how to tweak the WINEDEBUG env var. Looks like SEH structured exception handling is most useful for crashes ?

Getting a shell inside the steam runtime container

Checking FSYNC and ext4

There are a couple of kernel patches dvelopped to reduce wine layer overhead.