Skip to content
WSLDeep Dive Published Updated 7 min readViews unavailable

Shared Memory in WSL 2: /dev/shm, tmpfs, and Application Limits

Measure WSL 2 shared-memory capacity at the mount and process layers, then size workloads without mistaking tmpfs for durable disk.

Applications use shared memory for different purposes: POSIX shared-memory objects, System V segments, browser and database coordination, and containerized workloads that expect a usable /dev/shm. In Linux, /dev/shm is commonly a tmpfs mount. In WSL 2, that guest mount consumes resources from the Linux environment running inside the managed VM; it is not a durable Windows directory and it is not an unlimited pool separate from the WSL memory ceiling.

A process that reports “no space left” while creating a shared-memory object may be hitting the /dev/shm mount’s size limit, the WSL VM’s memory pressure, an application-specific limit, or a container’s private mount configuration. Measure the layer that failed before resizing anything.

Inspect the mount, not just the directory

Start with mount identity and both byte and inode capacity:

findmnt -T /dev/shm -o TARGET,SOURCE,FSTYPE,OPTIONS
df -hT /dev/shm
df -i /dev/shm
stat -f /dev/shm

The size shown for tmpfs is a configured maximum or mount accounting limit, not necessarily memory reserved at boot. Actual allocation grows with use and is subject to the guest’s memory and swap conditions. Do not interpret df’s displayed capacity as physical RAM permanently withheld from Windows. Conversely, a large configured tmpfs limit does not guarantee the WSL VM or Windows host has enough memory for every application to use it.

If /dev/shm is not a separate tmpfs mount, inspect the distro’s mount configuration and system startup. Avoid assuming every container or service sees the host distro’s same mount. A container can have a private namespace or an explicitly sized shared-memory mount, which changes the relevant path and capacity.

Distinguish POSIX and System V shared memory

POSIX shared-memory APIs commonly create named objects represented under /dev/shm on Linux. System V IPC segments are managed through separate kernel IPC interfaces. Inspect both when the application can use either:

ipcs -m
ipcs -s
ls -lah /dev/shm

A full directory listing is useful for POSIX objects but does not account for every System V segment. An orphan-looking filename is not automatically safe to remove: another process may still have it open or expect a stable name. Identify the owning application and process lifecycle before cleanup.

A minimal Python probe can verify that the current interpreter can create and release a POSIX shared-memory segment:

from multiprocessing import shared_memory

segment = shared_memory.SharedMemory(create=True, size=4096)
try:
    segment.buf[:4] = b"WSL2"
    print(bytes(segment.buf[:4]))
finally:
    segment.close()
    segment.unlink()

This tests a tiny object, not the application’s peak allocation or a container boundary. Run it from the same user, mount namespace, and service context as the workload. Some Python versions also manage resource-tracker behavior for shared memory; close and unlink according to the Python version’s documentation and application ownership model.

Find the boundary that imposed the limit

Compare the host distro view, the process environment, cgroup memory controls, and any container runtime settings. A service unit can have a memory limit; a container can set /dev/shm size independently; the WSL VM can have a global memory ceiling; Windows itself can be under pressure. These limits do not all appear in df output.

For containers, inspect the container’s mount and runtime configuration from inside the container. Docker exposes a shared-memory size option for containers; Podman and other runtimes have corresponding behavior that should be checked against the installed version. Do not raise a Linux host’s /dev/shm size and assume the container mount changed. Conversely, do not enlarge every container when the actual bottleneck is the overall WSL VM memory limit.

WSL’s global memory option applies to the VM and is configured in .wslconfig, not inside each distro. Changing it requires a WSL VM restart and affects all running WSL 2 distributions. Validate the currently effective memory and cgroup views rather than copying a sample size from a different machine. A systemd cgroup may account memory differently from tmpfs free space.

Resize only with a workload-based reason

Linux permits tmpfs mount sizing through mount options, but remount behavior and startup ownership matter. Before changing /dev/shm, capture its current options, distro startup path, and expected peak working set. A temporary remount can test a hypothesis, but it is not durable unless the configuration owner applies it after restart. Do not edit a generated WSL mount blindly or place duplicate definitions in /etc/fstab, wsl.conf, and systemd units.

The correct target size comes from a measured high-water mark with headroom for concurrent processes, not from the largest value accepted by mount. Increasing tmpfs capacity permits more pages to be allocated; those pages still need backing resources in the WSL VM and may contribute to memory pressure or swap activity. Test the full workload while observing guest memory, cgroup pressure, Windows host memory, and swap.

If the application allows shared-memory use to be configured, changing that application setting may be safer than enlarging the entire mount. If only a container needs more shared memory, adjust that container’s explicit size rather than every WSL process. Record why the limit changed and the rollback value.

Understand persistence and cleanup

Tmpfs is memory-backed filesystem behavior, not a durable disk volume. Objects do not survive a full WSL VM shutdown as persistent application data. Use it only for coordination or temporary data that can be recreated. A database or build artifact that must persist belongs on a durable filesystem and needs its own backup and recovery plan.

When cleaning up, stop the application that owns an object and use its supported shutdown path. Check open references before deleting named objects. Removing files from /dev/shm while a process uses them can change what future processes see without immediately freeing all resources. For System V IPC, use the application’s own cleanup or inspect ownership before using ipcrm. Blindly deleting every object may cause subtle failures in other services.

If a process exits unexpectedly, inspect its logs and kernel/systemd journal for allocation errors, then compare /dev/shm usage before and after restart. Check whether the object was recreated and whether the same application instance still holds an old reference. A successful service restart is not sufficient evidence that an undersized mount has been repaired.

Inspect shared-memory callers before increasing capacity

POSIX shm users can create named objects with shm_open and map them into processes; System V IPC has different identifiers and cleanup behavior. Applications may also use anonymous shared mappings that do not appear as named entries in /dev/shm. A directory listing is therefore not a complete accounting of all memory sharing. Use application diagnostics and kernel counters alongside df and ipcs.

For a browser or database, correlate allocation failures with the application’s own logs, worker count, and restart behavior. If a workload creates a high number of small objects, inode capacity can matter as well as bytes. If it creates a few large mappings, memory limit and swap conditions are more likely. Record whether the error is ENOSPC, allocation failure, or process termination; similar user-facing messages can arise from different resource limits.

Acceptance test for browser, database, and container workloads

Choose representative operations that exercise the actual shared-memory path. Record the process user, mount options, cgroup or container limit, WSL VM memory setting, object or segment size, peak /dev/shm use, host memory pressure, and swap. Run with the normal number of concurrent workers, not a single-process smoke test.

For a containerized application, verify from inside the container that /dev/shm has the intended size and that a disposable allocation succeeds. For a system service, repeat after a fresh distro start so an interactive-shell remount does not mask missing persistent configuration. Confirm that data intended to survive restart is not stored only in tmpfs.

Troubleshooting decision tree

If df -h shows the mount full while the WSL VM has available memory, inspect the configured tmpfs limit or container-specific mount. If the mount has room but allocations fail, inspect process limits, cgroups, kernel logs, and application constraints. If the guest has memory pressure, adjust workload concurrency or the WSL VM budget only after measuring host capacity. If objects remain after a failed application, identify ownership before cleanup.

Keep /dev/shm capacity, tmpfs memory consumption, Linux cgroup limits, WSL VM memory settings, and Windows physical memory as separate readings in incident notes. That separation makes a WSL shared-memory failure diagnosable and avoids “fixing” a per-container limit by taking memory away from every other distro.

Related:

Sources:

Comments