IPDL/Shmem
Introduction
IPDL provides a built-in Shmem type. Shmem represents a segment of memory mapped into both a parent's and child's address space. Shmems are used to avoid copying large amounts of data across the IPC pipe.
Ownership model
The model is very simple: at any given time, a Shmem is owned by either the parent or the child. Only the owner has read/write privileges; the other side has no privileges. One side transfers ownership of a Shmem to the other by sending the Shmem in an IPDL message, or returning it in a reply to a synchronous message.
It's illegal for C++ code to read/write a Shmem it doesn't own. We enforce ownership semantics by mapping segments with full read/write access in the owning process, and mapping them with no access in the other process. C++ code that violates the ownership model will die from a SEGFAULT.
Using Shmem in protocols
sync protocol UsesShmem {
child:
// transfers ownership of |s| from parent to child
async HereYouGo(Shmem s);
parent:
// transfers ownership of |s| from child to parent, then back to child
sync GiveAndGetBack(Shmem s) returns (Shmem ss);
// transfers ownership of |s| from child to parent
async ThanksDone(Shmem s);
};
Using Shmem in C++
class Foo : public UsesShmemParent {
using mozilla::ipc::Shmem;
Shmem mShmem;
bool Init() {
// this may fail; always check return value
if (!AllocShmem(&mShmem, 10000))
return false;
// get() and Size() check for proper alignment of the segment
memset(mShmem.get<char>(), 0, mShmem.Size<char>());
}
bool Foo() {
// [do stuff]
char* p = mShmem.get<char>();
if (!SendHereYouGo(mShmem))
return false;
// mShmem is now unusable; both of the following would fail:
// *p = 1;
// mShmem.get<char>();
}
NS_OVERRIDE virtual bool
RecvGiveAndGetBack(Shmem& s, Shmem* ss) {
// we own |s| again
// [do stuff with |s|]
*ss = s;
// when this method returns, we don't own |s| anymore
}
NS_OVERRIDE virtual bool
RecvThanksDone(Shmem& s) {
// we own |s| again
mShmem = s;
}
};
Shmems are automatically managed by IPDL-generated code. When your protocol tree is deleted, all Shmems still open are unmapped and deleted.
Aside: it's not necessary to know this, but Shmems are actually just handles to other objects managed by IPDL-generated code.
"Unsafe" Shmem
Code that has special needs can allocate "unsafe" Shmem. "Unsafe" Shmem allows full read/write access by all processes with a reference to the segment. This means that data races are possible, unlike with normal Shmem. To create a segment, use the interface AllocUnsafeShmem() instead of AllocShmem(). Use with care.