During dump and restore operations, CRIU requires numerous internal file descriptors (FDs) to manage logs, images, RPC communication, and transport sockets. Because the application being checkpointed or restored may use any arbitrary FD number, CRIU must ensure its internal descriptors never conflict with those of the application. To achieve this, CRIU uses the Service FD Engine.
CRIU avoids FD collisions by placing its internal descriptors in a “protected” range at the very top of the process’s file descriptor table.
RLIMIT_NOFILE resource limit (using rlimit_unlimit_nofile()) to a very high value (typically 1,048,576 or higher).The engine (criu/servicefd.c) provides a robust abstraction for managing these descriptors through several key techniques:
In scenarios where multiple processes share the same file descriptor table (e.g., threads or processes created with CLONE_FILES), CRIU assigns a unique service_fd_id to each task. The engine uses this ID to offset the service FD range, ensuring that even tasks sharing an FD table have distinct, non-overlapping slots for their internal CRIU descriptors.
When CRIU opens a file for its own use (such as an image file or the log), the kernel initially assigns it the lowest available FD number (e.g., FD 3). CRIU then uses fcntl(F_DUPFD_CLOEXEC) or dup3() to “move” that descriptor to its designated high-range slot and immediately closes the original low-numbered descriptor.
During critical phases of restoration—specifically when the application’s FDs are being “planted” into their final numeric slots—CRIU sets a global sfds_protected flag. While this flag is set, the service FD engine is “locked.” Any attempt by the code to modify or close a service descriptor will trigger an immediate safety crash (BUG), preventing accidental corruption of the restoration state.
The engine manages various types of descriptors, each with a specific role:
SCM_RIGHTS./proc filesystem.