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.