GSoC 2026 Draft Proposal (Checkpointing of POSIX Message Queues)
Ojo Boluwatife Fiyinfoluwa <[email protected]> Sun, 15 Mar 2026 07:47:43 +0100
| Newsgroups | dev.linux.lists.criu |
|---|---|
| Message-ID | <[email protected]> |
Hello Radostin and Pavel, I hope you are doing well. Following our earlier exchange, I have completed my draft proposal for the POSIX message queues project and would be grateful for your feedback before I submit it on the GSoC portal tomorrow. Since we last spoke, I have: - Studied August Fu's implementation in full and identified the gap: intrusive_mq_peek_all() is a temporary read-resend hack with no kernel interface behind it - Traced the dump failure to criu/files-reg.c:1710 - Read commit 8ce9e947051e (SO_PEEK_OFF) as the reference pattern for the kernel interface - Had PR #2963 merged (CodeQL actions v3 → v4 upgrade) My proposal covers my full technical approach (a new ioctl in ipc/mqueue.c, CRIU dump/restore integration building on Fu's scaffolding, and extended ZDTM tests for priority ordering and edge cases.) I have attached the proposal as a plain text document. Any feedback on the technical approach or timeline would be very welcome. Thank you for your time. Ojo Boluwatife Fiyinfoluwa GitHub: https://github.com/fiyinfoluwa001 Gitter: @fiyinfoluwa:gitter.im PROJECT TITLE: Checkpointing of POSIX message queues MENTORS: Radostin Stoyanov <[email protected]> Pavel Tikhomirov <[email protected]> PERSONAL INFORMATION: Name: Ojo Boluwatife Fiyinfoluwa Email: [email protected] Github: https://github.com/fiyinfoluwa001 Gitter: @fiyinfoluwa:gitter.im Location: Lagos, Nigeria Timezone: GMT + 1 PROBLEM STATEMENT The problem The main issue is how the system handles messages. In the present linux code, specifically a file called mqueue.c there is currently only one way to read a message: pick it up and then take it out. Just like a physical email box where the moment you view a letter, it just disappears or vaporizes, this phenomenon is what is called a destructive read. There is no function where you could quickly take a look at the message while it’s left safely on the queue. CRIU (Checkpoint/Restore In Userspace) acts as a button for running programs. It freezes a program => Saves its state to a file => Lets you restart it later on. To achieve the above process, CRIU needs to see what messages would be waiting in the inbox, but due to the destructive read or the self destruct rule: CRIU reads the messages to save them → but reading removes them from the queue → so the saved state is now broken because the original queue is empty. When CRIU encounters a POSIX message queue file descriptor today, it fails at line 1710 in criu/files-reg.c with the error: Can't lookup mount for fd path=/mq0. In other parts of Linux like the Unix domain sockets, there is a command called the MSG_PEEK, this command lets you peek at a message without removing it. POSIX message queues don’t have that command. Yet. Why CRIU currently fails When trying to use CRIU to save a program that uses this message queues, it gets confused. The path problem : CRIU looks for the queue (like /mq0) and can’t find where it lives on the system, it hits a dead end in its code and simply gives up. The safety problem: Even if it found the queue it would not know how to peek at the messages without deleting them. A prior contributor (August Fu) tried solving this problem by building a temporary framework (scaffolding). Fu created the fd detection logic, a new criu/mqueue.c, a protobuf schema in images/mqueue.proto, and a ZDTM test — everything except the kernel interface itself. To save messages, this contributor had to do something risky: * Read the message (which then deletes it from the queue) * Save the data to a file * Re-send the message back into the queue immediately As the contributor himself noted in the code that the ‘read-re-send ’ hack was temporary, this is dangerous because: * It changes the timing of the message * If the system crashes halfway through the process, the message is lost forever The only real way to fix this issue is to go into the linux kernel itself and then add a peek feature ( a way for CRIU to look at the messages through a window without touching them). https://raw.githubusercontent.com/fiyinfoluwa001/criu/criu-dev/diagrams/criu-img-proposal.png The solution: Using sockets as a map This problem was solved by CRIU for UNIX sockets. Sockets originally had the same ‘read => delete’ issue, but this issue was resolved by adding a feature called SO_PEEK_OFF This acts like a digital bookmarker: * It lets CRIU read data from a socket without consuming it, this preserves the original state. This same principle (read without destroying), is what POSIX message queues need. https://raw.githubusercontent.com/fiyinfoluwa001/criu/criu-dev/diagrams/criu-img-solution.png TECHNICAL APPROACH The Kernel Patch We would be focusing on a file called ipc/mqueue.c. My first approach would be to add a new command (an ioctl) that would help us look at the messages without taking anything out. This is how it would function: * Find the inbox (It would take the file descriptor of the message queue as input). * Walkthrough(Inside the kernel, messages are stored in an rb-tree, this new command would walk through this tree, starting with the most important messages). * As it is moving through this tree, it copies the content and the priority level of every message into a safe buffer for the user, and then it tells the user exactly how many messages it found and copied. * The most important action here is that the command leaves the original tree exactly as it found it, nothing is deleted or removed. By adding this feature, we provide a safer way to back up the queue without destroying data.The data structure that holds each message would look like this struct mq_peek_msg { unsigned int priority; size_t msg_len; char msg_ptr[MQ_MSGSIZE_MAX]; }; The CRIU Userspace (Dump) The Detection When CRIU starts the process of saving a program, it checks or looks at every open file, for this I would be adding a check specifically the dump_one_file() in criu/files.c to recognize the POSIX_MQUEUE_MAGIC ID. This process tells CRIU that it is not a normal file but a message queue. The Retrieval Once CRIU is informed that it’s not a normal file but a queue, it will call a new function. Instead of using the old way of deleting and re-sending messages, it would use the new kernel command (ioctl) to safely copy all messages at once without touching the original queue. Saving to Image All the data is taken and then packaged: * The body and priority of every message are saved using the mqueue.proto schema, the one Fu defined that captures both the message body and the priority integer.. * The queue’s rules (maxmsg, msgsize, curmsgs)are also recorded using mq_getattr() Cleaning Up Code The helpful part of August Fu’s work would be kept and the band-aid fix would be cut out. I’ll be replacing the temporary read-resend function with the clean kernel call. The CRIU Userspace (Restore) Rebuilding the inbox It starts by creating a brand new message queue using the settings saved earlier, using mq_open() with O_CREAT and the saved maxmsg and msgsize attributes to ensure the new inbox has the same limits, like the maximum number of messages and the allowed message size as the original one. Replaying the messages CRIU goes through the saved list of messages one after the other, looking at each message’s body and its priority level. It would then send them into the new queue mq_send, because each message's priority integer was saved individually, the kernel's priority queue automatically places them back in the correct order, no manual sorting necessary. Fixing the ID Every open file or queue in a program has a specific file descriptor. To ensure the restored program does not get confused, using dup2 , following the same pattern used in criu/pidfd.c to give the new queue the exact same ID number the old one had. Keeping it clean All this would be built off of the ground work of the previous developer for this part, since the save method is now non-destructive, the restore is much more reliable. Tests Improving Existing Tests (test/zdtm/static/pmsgque.c) * Priority Order: I’ll send messages with different importance levels to make sure they come out in the right order after a restore. * Full Queues: I’ll test a scenario where the inbox is completely full to ensure that no data is dropped. * Empty queue: verify CRIU handles a queue with zero messages gracefully, no crash, clean restore. * Multiple Connections: I’ll test scenarios where even if a program has several different handles open on the same queue. Kernel Safety Tests (kselftest, tools/testing/selftests/ipc/) * Ensure the new ‘peek’ command (ioctl) returns the exact right data * The command is truly non-destructive and doesn’t change a single bit of the original queue TIMELINE Community Bonding (May 1 - June 1) * Research kernel’s internal message systems with mentors guidance * Confirm the best technical interface with mentors. * Set up specialized virtual machine for deep-level kernel debugging * Review open CI and workflow issues on criu-dev branch and contribute where possible Week 1 - 2 (June 2 - 15) : Kernel (Design and scaffolding) * Create data format and command ID in the kernel header files * Write initial command handler in ipc/mqueue.c that compiles but doesn’t perform actions yet * Send a short RFC email to mentors documenting design decisions and confirming interface approach Week 3 - 4 (June 16 - 29) : Kernel (Implementation) * Write the code that scans through the message tree while keeping the data safely locked. * Ensure the system correctly handles empty queues, full queues and very large messages. * Create a simple program to verify that the new command retrieves data correctly from the kernel. Week 5 – 6 (June 30 – July 13) : Kernel (Test and Review) * Create kselftest suite to prove the new command works correctly * Update kernel patch based on my mentor’s technical feedback * Prepare the final code for the official Linux Kernel mailing list Week 7(July 14 - July 20) : Buffer * Finish any leftover kernel work or documentation * Research how CRIU handles other special files to prepare for the ‘Save’ feature. * Read criu/pidfd.c and criu/unixsk.c in depth to understand the fd handling patterns you'll follow in Week 8-9 Week 8 – 9 (July 21 - August 3) : CRIU (Dump) * Update CRIU to automatically recognize POSIX message queues during a scan * Write the code to pull message data from the kernel and save it to the file * Double check that the saved image files contain the correct message bodies and priorities Week 10 - 11 (August 4 - 17) : CRIU (Restore and Test) * Create the ‘restore’ logic to rebuild the queue and reload messages in their original order. * Update the pmsgque.c test to check for complex scenarios like priority sorting and full queues * Run the entire suite of CRIU tests to ensure the new features don’t break existing ones. Week 12 (August 18 - 24) : CRIU (Buffer and Polish) * Update my work based on mentors feedback * Add instruction for POSIX message queue support to the CRIU wiki page. * Perform a complete cleanup to ensure all tests pass on the automated system Final Evaluation(August 25) * Confirm kernel patch is under review on the Linux kernel mailing list * Open the official PR to add message queue support to CRIU * Verify that every single test case passes successfully. Post Contribution * Address any remaining review feedback on the kernel patch from the linux kernel mailing list * Remain available to help future contributors building on this work * Continue contributing to CRIU beyond the scope of this project. PRIOR CONTRIBUTIONS AND ENGAGEMENT Codebase Study * Built CRIU v4.2 from source on Ubuntu 24.04 (kernel 6.8) and then ran a successful checkpoint/restore cycle * Wrote and ran a C demo program demonstrating the exact problem: mq_receive() is destructive, messages are lost on read * Read August Fu's implementation at github.com/yuntongf/criu (branch: posix-mqueue) in full, identifying the gap: intrusive_mq_peek_all() is acknowledged by Fu himself as temporary. * Traced the dump failure to criu/files-reg.c:1710 and understood why it happens * Read commit 8ce9e947051e (SO_PEEK_OFF socket support) as the reference pattern for this project * Merged PR #2963 , upgraded CodeQL actions from v3 to v4 ahead of Node.js 20 end-of-life (April 30, 2026) CI Investigation (Issue #2911) * Investigated two failing CI runs (Run #42 and #43) identifying a consistent network bridge teardown race condition in the compat-test job. Issue was subsequently resolved in PRs #2950 and #2948 ABOUT ME I am a software developer (backend heavy) in Lagos, Nigeria, with a background in C, Linux systems programming, Bash, Javascript and Typescript, I am also a penultimate year student at Obafemi Awolowo University, Ile-Ife, Osun state,Nigeria, studying Computer Engineering. I have been working on Ubuntu 24.04 (kernel 6.8) and have spent the past month studying and building genuine familiarity with the CRIU codebase, not just reading documentation but also by building the project from source, running checkpoint/restore cycles and writing C programs to demonstrate the exact problem that my proposal solves. I chose this project because the problem is specific and the solution path is clear. After studying August Fu’s prior implementation, I identified that the missing piece is not userspace code but a kernel interface that does not exist yet. That gap is what I intend to fill. I have no competing commitments during the summer and I am available to work full time on this project for the full 350 hrs.
GSoC-CRIU-PROPOSAL.txt
(text/plain, 12.6 KB)
PROJECT TITLE: Checkpointing of POSIX message queues MENTORS: Radostin Stoyanov <[email protected]> Pavel Tikhomirov <[email protected]> PERSONAL INFORMATION: Name: Ojo Boluwatife Fiyinfoluwa Email: [email protected] Github: https://github.com/fiyinfoluwa001 Gitter: @fiyinfoluwa:gitter.im Location: Lagos, Nigeria Timezone: GMT + 1 PROBLEM STATEMENT The problem The main issue is how the system handles messages. In the present linux code, specifically a file called mqueue.c there is currently only one way to read a message: pick it up and then take it out. Just like a physical email box where the moment you view a letter, it just disappears or vaporizes, this phenomenon is what is called a destructive read. There is no function where you could quickly take a look at the message while it’s left safely on the queue. CRIU (Checkpoint/Restore In Userspace) acts as a button for running programs. It freezes a program => Saves its state to a file => Lets you restart it later on. To achieve the above process, CRIU needs to see what messages would be waiting in the inbox, but due to the destructive read or the self destruct rule: CRIU reads the messages to save them → but reading removes them from the queue → so the saved state is now broken because the original queue is empty. When CRIU encounters a POSIX message queue file descriptor today, it fails at line 1710 in criu/files-reg.c with the error: Can't lookup mount for fd path=/mq0. In other parts of Linux like the Unix domain sockets, there is a command called the MSG_PEEK, this command lets you peek at a message without removing it. POSIX message queues don’t have that command. Yet. Why CRIU currently fails When trying to use CRIU to save a program that uses this message queues, it gets confused. The path problem : CRIU looks for the queue (like /mq0) and can’t find where it lives on the system, it hits a dead end in its code and simply gives up. The safety problem: Even if it found the queue it would not know how to peek at the messages without deleting them. A prior contributor (August Fu) tried solving this problem by building a temporary framework (scaffolding). Fu created the fd detection logic, a new criu/mqueue.c, a protobuf schema in images/mqueue.proto, and a ZDTM test — everything except the kernel interface itself. To save messages, this contributor had to do something risky: * Read the message (which then deletes it from the queue) * Save the data to a file * Re-send the message back into the queue immediately As the contributor himself noted in the code that the ‘read-re-send ’ hack was temporary, this is dangerous because: * It changes the timing of the message * If the system crashes halfway through the process, the message is lost forever The only real way to fix this issue is to go into the linux kernel itself and then add a peek feature ( a way for CRIU to look at the messages through a window without touching them). https://raw.githubusercontent.com/fiyinfoluwa001/criu/criu-dev/diagrams/criu-img-proposal.png The solution: Using sockets as a map This problem was solved by CRIU for UNIX sockets. Sockets originally had the same ‘read => delete’ issue, but this issue was resolved by adding a feature called SO_PEEK_OFF This acts like a digital bookmarker: * It lets CRIU read data from a socket without consuming it, this preserves the original state. This same principle (read without destroying), is what POSIX message queues need. https://raw.githubusercontent.com/fiyinfoluwa001/criu/criu-dev/diagrams/criu-img-solution.png TECHNICAL APPROACH The Kernel Patch We would be focusing on a file called ipc/mqueue.c. My first approach would be to add a new command (an ioctl) that would help us look at the messages without taking anything out. This is how it would function: * Find the inbox (It would take the file descriptor of the message queue as input). * Walkthrough(Inside the kernel, messages are stored in an rb-tree, this new command would walk through this tree, starting with the most important messages). * As it is moving through this tree, it copies the content and the priority level of every message into a safe buffer for the user, and then it tells the user exactly how many messages it found and copied. * The most important action here is that the command leaves the original tree exactly as it found it, nothing is deleted or removed. By adding this feature, we provide a safer way to back up the queue without destroying data.The data structure that holds each message would look like this struct mq_peek_msg { unsigned int priority; size_t msg_len; char msg_ptr[MQ_MSGSIZE_MAX]; }; The CRIU Userspace (Dump) The Detection When CRIU starts the process of saving a program, it checks or looks at every open file, for this I would be adding a check specifically the dump_one_file() in criu/files.c to recognize the POSIX_MQUEUE_MAGIC ID. This process tells CRIU that it is not a normal file but a message queue. The Retrieval Once CRIU is informed that it’s not a normal file but a queue, it will call a new function. Instead of using the old way of deleting and re-sending messages, it would use the new kernel command (ioctl) to safely copy all messages at once without touching the original queue. Saving to Image All the data is taken and then packaged: * The body and priority of every message are saved using the mqueue.proto schema, the one Fu defined that captures both the message body and the priority integer.. * The queue’s rules (maxmsg, msgsize, curmsgs)are also recorded using mq_getattr() Cleaning Up Code The helpful part of August Fu’s work would be kept and the band-aid fix would be cut out. I’ll be replacing the temporary read-resend function with the clean kernel call. The CRIU Userspace (Restore) Rebuilding the inbox It starts by creating a brand new message queue using the settings saved earlier, using mq_open() with O_CREAT and the saved maxmsg and msgsize attributes to ensure the new inbox has the same limits, like the maximum number of messages and the allowed message size as the original one. Replaying the messages CRIU goes through the saved list of messages one after the other, looking at each message’s body and its priority level. It would then send them into the new queue mq_send, because each message's priority integer was saved individually, the kernel's priority queue automatically places them back in the correct order, no manual sorting necessary. Fixing the ID Every open file or queue in a program has a specific file descriptor. To ensure the restored program does not get confused, using dup2 , following the same pattern used in criu/pidfd.c to give the new queue the exact same ID number the old one had. Keeping it clean All this would be built off of the ground work of the previous developer for this part, since the save method is now non-destructive, the restore is much more reliable. Tests Improving Existing Tests (test/zdtm/static/pmsgque.c) * Priority Order: I’ll send messages with different importance levels to make sure they come out in the right order after a restore. * Full Queues: I’ll test a scenario where the inbox is completely full to ensure that no data is dropped. * Empty queue: verify CRIU handles a queue with zero messages gracefully, no crash, clean restore. * Multiple Connections: I’ll test scenarios where even if a program has several different handles open on the same queue. Kernel Safety Tests (kselftest, tools/testing/selftests/ipc/) * Ensure the new ‘peek’ command (ioctl) returns the exact right data * The command is truly non-destructive and doesn’t change a single bit of the original queue TIMELINE Community Bonding (May 1 - June 1) * Research kernel’s internal message systems with mentors guidance * Confirm the best technical interface with mentors. * Set up specialized virtual machine for deep-level kernel debugging * Review open CI and workflow issues on criu-dev branch and contribute where possible Week 1 - 2 (June 2 - 15) : Kernel (Design and scaffolding) * Create data format and command ID in the kernel header files * Write initial command handler in ipc/mqueue.c that compiles but doesn’t perform actions yet * Send a short RFC email to mentors documenting design decisions and confirming interface approach Week 3 - 4 (June 16 - 29) : Kernel (Implementation) * Write the code that scans through the message tree while keeping the data safely locked. * Ensure the system correctly handles empty queues, full queues and very large messages. * Create a simple program to verify that the new command retrieves data correctly from the kernel. Week 5 – 6 (June 30 – July 13) : Kernel (Test and Review) * Create kselftest suite to prove the new command works correctly * Update kernel patch based on my mentor’s technical feedback * Prepare the final code for the official Linux Kernel mailing list Week 7(July 14 - July 20) : Buffer * Finish any leftover kernel work or documentation * Research how CRIU handles other special files to prepare for the ‘Save’ feature. * Read criu/pidfd.c and criu/unixsk.c in depth to understand the fd handling patterns you'll follow in Week 8-9 Week 8 – 9 (July 21 - August 3) : CRIU (Dump) * Update CRIU to automatically recognize POSIX message queues during a scan * Write the code to pull message data from the kernel and save it to the file * Double check that the saved image files contain the correct message bodies and priorities Week 10 - 11 (August 4 - 17) : CRIU (Restore and Test) * Create the ‘restore’ logic to rebuild the queue and reload messages in their original order. * Update the pmsgque.c test to check for complex scenarios like priority sorting and full queues * Run the entire suite of CRIU tests to ensure the new features don’t break existing ones. Week 12 (August 18 - 24) : CRIU (Buffer and Polish) * Update my work based on mentors feedback * Add instruction for POSIX message queue support to the CRIU wiki page. * Perform a complete cleanup to ensure all tests pass on the automated system Final Evaluation(August 25) * Confirm kernel patch is under review on the Linux kernel mailing list * Open the official PR to add message queue support to CRIU * Verify that every single test case passes successfully. Post Contribution * Address any remaining review feedback on the kernel patch from the linux kernel mailing list * Remain available to help future contributors building on this work * Continue contributing to CRIU beyond the scope of this project. PRIOR CONTRIBUTIONS AND ENGAGEMENT Codebase Study * Built CRIU v4.2 from source on Ubuntu 24.04 (kernel 6.8) and then ran a successful checkpoint/restore cycle * Wrote and ran a C demo program demonstrating the exact problem: mq_receive() is destructive, messages are lost on read * Read August Fu's implementation at github.com/yuntongf/criu (branch: posix-mqueue) in full, identifying the gap: intrusive_mq_peek_all() is acknowledged by Fu himself as temporary. * Traced the dump failure to criu/files-reg.c:1710 and understood why it happens * Read commit 8ce9e947051e (SO_PEEK_OFF socket support) as the reference pattern for this project * Merged PR #2963 , upgraded CodeQL actions from v3 to v4 ahead of Node.js 20 end-of-life (April 30, 2026) CI Investigation (Issue #2911) * Investigated two failing CI runs (Run #42 and #43) identifying a consistent network bridge teardown race condition in the compat-test job. Issue was subsequently resolved in PRs #2950 and #2948 ABOUT ME I am a software developer (backend heavy) in Lagos, Nigeria, with a background in C, Linux systems programming, Bash, Javascript and Typescript, I am also a penultimate year student at Obafemi Awolowo University, Ile-Ife, Osun state,Nigeria, studying Computer Engineering. I have been working on Ubuntu 24.04 (kernel 6.8) and have spent the past month studying and building genuine familiarity with the CRIU codebase, not just reading documentation but also by building the project from source, running checkpoint/restore cycles and writing C programs to demonstrate the exact problem that my proposal solves. I chose this project because the problem is specific and the solution path is clear. After studying August Fu’s prior implementation, I identified that the missing piece is not userspace code but a kernel interface that does not exist yet. That gap is what I intend to fill. I have no competing commitments during the summer and I am available to work full time on this project for the full 350 hrs.