Index: mojo/system/handle_table.h |
diff --git a/mojo/system/handle_table.h b/mojo/system/handle_table.h |
index 96f7abae7450353316440ecd1b3bf325df74f92f..1ccc96433700b1898053a478df870efc47831b5e 100644 |
--- a/mojo/system/handle_table.h |
+++ b/mojo/system/handle_table.h |
@@ -101,6 +101,23 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable { |
private: |
friend bool internal::ShutdownCheckNoLeaks(Core*); |
+ // The |busy| member is used only to deal with functions (in particular |
+ // |Core::WriteMessage()|) that want to hold on to a dispatcher and later |
+ // remove it from the handle table, without holding on to the handle table |
+ // lock. |
+ // |
+ // For example, if |Core::WriteMessage()| is called with a handle to be sent, |
+ // (under the handle table lock) it must first check that that handle is not |
+ // busy (if it is busy, then it fails with |MOJO_RESULT_BUSY|) and then marks |
+ // it as busy. To avoid deadlock, it should also try to acquire the locks for |
+ // all the dispatchers for the handles that it is sending (and fail with |
+ // |MOJO_RESULT_BUSY| if the attempt fails). At this point, it can release the |
+ // handle table lock. |
+ // |
+ // If |Core::Close()| is simultaneously called on that handle, it too checks |
+ // if the handle is marked busy. If it is, it fails (with |MOJO_RESULT_BUSY|). |
+ // This prevents |Core::WriteMessage()| from sending a handle that has been |
+ // closed (or learning about this too late). |
struct Entry { |
Entry(); |
explicit Entry(const scoped_refptr<Dispatcher>& dispatcher); |