IPDL/Shmem

< IPDL

Contents

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.