Skip to content

Commit 7262779

Browse files
committed
Bug 1850865: Improve MOZ_IPC_MESSAGE_LOG. r=ipc-reviewers,nika
Use MOZ_IPC_MESSAGE_LOG to filter GOODBYE_MESSAGE_TYPE messages. Interpret MOZ_IPC_MESSAGE_LOG elements without the "Child" or "Parent" suffix as a request to log both sides of the given protocol. Differential Revision: https://phabricator.services.mozilla.com/D187167
1 parent 884175b commit 7262779

File tree

7 files changed

+91
-46
lines changed

7 files changed

+91
-46
lines changed

ipc/docs/ipdl.rst

+14-6
Original file line numberDiff line numberDiff line change
@@ -1756,11 +1756,19 @@ The environment variable ``MOZ_IPC_MESSAGE_LOG`` controls the logging of IPC
17561756
messages. It logs details about the transmission and reception of messages.
17571757
This isn't controlled by ``MOZ_LOG`` -- it is a separate system. Set this
17581758
variable to ``1`` to log information on all IPDL messages, or specify a
1759-
comma-separated list of **top-level** protocols to log (e.g.
1760-
``MOZ_IPC_MESSAGE_LOG="PMyManagerChild,PMyManagedParent,PMyManagedChild"``).
1759+
comma-separated list of protocols to log.
1760+
If the ``Child`` or ``Parent`` suffix is given, then only activity on the given
1761+
side is logged; otherwise, both sides are logged. All protocol names must
1762+
include the ``P`` prefix.
1763+
1764+
For example:
1765+
1766+
.. code-block::
1767+
1768+
MOZ_IPC_MESSAGE_LOG="PMyManagerChild,PMyManaged"
1769+
1770+
This requests logging of child-side activity on ``PMyManager``, and both
1771+
parent- and child-side activity on ``PMyManaged``.
1772+
17611773
:ref:`Debugging with IPDL Logging` has an example where IPDL logging is useful
17621774
in tracking down a bug.
1763-
1764-
.. important::
1765-
The preceding ``P`` and the ``Parent`` or ``Child`` suffix are required
1766-
when listing individual protocols in ``MOZ_IPC_MESSAGE_LOG``.

ipc/docs/processes.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ section on :ref:`Message Logging`. We just need to set an environment variable
11601160
before starting the browser. Let's turn it on for all ``PDemo`` and
11611161
``PDemoHelpline`` actors: ::
11621162

1163-
MOZ_IPC_MESSAGE_LOG="PDemoParent,PDemoChild,PDemoHelplineParent,PDemoHelplineChild"
1163+
MOZ_IPC_MESSAGE_LOG="PDemo,PDemoHelpline"
11641164

11651165
To underscore what we said above, when logging is active, the change in timing
11661166
makes the error message go away and everything closes properly on a tested

ipc/glue/MessageChannel.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -941,13 +941,14 @@ bool MessageChannel::MaybeInterceptSpecialIOMessage(const Message& aMsg) {
941941
// ourselves as "Closing".
942942
mLink->Close();
943943
mChannelState = ChannelClosing;
944-
if (LoggingEnabled()) {
944+
if (LoggingEnabledFor(mListener->GetProtocolName(), mSide)) {
945945
printf(
946-
"[%s %u] NOTE: %s actor received `Goodbye' message. Closing "
946+
"[%s %u] NOTE: %s%s actor received `Goodbye' message. Closing "
947947
"channel.\n",
948948
XRE_GeckoProcessTypeToString(XRE_GetProcessType()),
949949
static_cast<uint32_t>(base::GetCurrentProcId()),
950-
(mSide == ChildSide) ? "child" : "parent");
950+
mListener->GetProtocolName(),
951+
(mSide == ChildSide) ? "Child" : "Parent");
951952
}
952953

953954
// Notify the worker thread that the connection has been closed, as we

ipc/glue/ProtocolUtils.cpp

+33-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#endif
2626
#include "mozilla/Unused.h"
2727
#include "nsPrintfCString.h"
28+
#include "nsReadableUtils.h"
2829

2930
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
3031
# include "mozilla/sandboxTarget.h"
@@ -104,10 +105,20 @@ void AnnotateCrashReportWithErrno(CrashReporter::Annotation tag, int error) {
104105
#endif // defined(XP_MACOSX)
105106

106107
#if defined(DEBUG) || defined(FUZZING)
108+
// If aTopLevelProtocol matches any token in aFilter, return true.
109+
//
110+
// aTopLevelProtocol is a protocol name, without the "Parent" / "Child" suffix.
111+
// aSide indicates whether we're logging parent-side or child-side activity.
112+
//
113+
// aFilter is a list of protocol names separated by commas and/or
114+
// spaces. These may include the "Child" / "Parent" suffix, or omit
115+
// the suffix to log activity on both sides.
116+
//
107117
// This overload is for testability; application code should use the single-
108118
// argument version (defined in the ProtocolUtils.h) which takes the filter from
109119
// the environment.
110-
bool LoggingEnabledFor(const char* aTopLevelProtocol, const char* aFilter) {
120+
bool LoggingEnabledFor(const char* aTopLevelProtocol, Side aSide,
121+
const char* aFilter) {
111122
if (!aFilter) {
112123
return false;
113124
}
@@ -119,9 +130,27 @@ bool LoggingEnabledFor(const char* aTopLevelProtocol, const char* aFilter) {
119130
Tokenizer tokens(aFilter, kDelimiters);
120131
Tokenizer::Token t;
121132
while (tokens.Next(t)) {
122-
if (t.Type() == Tokenizer::TOKEN_WORD &&
123-
t.AsString() == aTopLevelProtocol) {
124-
return true;
133+
if (t.Type() == Tokenizer::TOKEN_WORD) {
134+
auto filter = t.AsString();
135+
136+
// Since aTopLevelProtocol never includes the "Parent" / "Child" suffix,
137+
// this will only occur when filter doesn't include it either, meaning
138+
// that we should log activity on both sides.
139+
if (filter == aTopLevelProtocol) {
140+
return true;
141+
}
142+
143+
if (aSide == ParentSide &&
144+
StringEndsWith(filter, nsDependentCString("Parent")) &&
145+
Substring(filter, 0, filter.Length() - 6) == aTopLevelProtocol) {
146+
return true;
147+
}
148+
149+
if (aSide == ChildSide &&
150+
StringEndsWith(filter, nsDependentCString("Child")) &&
151+
Substring(filter, 0, filter.Length() - 5) == aTopLevelProtocol) {
152+
return true;
153+
}
125154
}
126155
}
127156

ipc/glue/ProtocolUtils.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -566,12 +566,15 @@ inline bool LoggingEnabled() {
566566
}
567567

568568
#if defined(DEBUG) || defined(FUZZING)
569-
bool LoggingEnabledFor(const char* aTopLevelProtocol, const char* aFilter);
569+
bool LoggingEnabledFor(const char* aTopLevelProtocol, mozilla::ipc::Side aSide,
570+
const char* aFilter);
570571
#endif
571572

572-
inline bool LoggingEnabledFor(const char* aTopLevelProtocol) {
573+
inline bool LoggingEnabledFor(const char* aTopLevelProtocol,
574+
mozilla::ipc::Side aSide) {
573575
#if defined(DEBUG) || defined(FUZZING)
574-
return LoggingEnabledFor(aTopLevelProtocol, PR_GetEnv("MOZ_IPC_MESSAGE_LOG"));
576+
return LoggingEnabledFor(aTopLevelProtocol, aSide,
577+
PR_GetEnv("MOZ_IPC_MESSAGE_LOG"));
575578
#else
576579
return false;
577580
#endif

ipc/gtest/TestLogging.cpp

+25-16
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,51 @@ namespace mozilla::ipc {
1414
TEST(IPCLogging, EmptyFilter)
1515
{
1616
const char* emptyFilter = "";
17-
EXPECT_FALSE(LoggingEnabledFor("PContentParent", emptyFilter));
18-
EXPECT_FALSE(LoggingEnabledFor("PContentChild", emptyFilter));
17+
EXPECT_FALSE(LoggingEnabledFor("PContent", ParentSide, emptyFilter));
18+
EXPECT_FALSE(LoggingEnabledFor("PContent", ChildSide, emptyFilter));
1919
}
2020

2121
TEST(IPCLogging, SingleProtocolFilter)
2222
{
2323
const char* contentParentFilter = "PContentParent";
24-
EXPECT_TRUE(LoggingEnabledFor("PContentParent", contentParentFilter));
25-
EXPECT_FALSE(LoggingEnabledFor("PContentChild", contentParentFilter));
24+
EXPECT_TRUE(LoggingEnabledFor("PContent", ParentSide, contentParentFilter));
25+
EXPECT_FALSE(LoggingEnabledFor("PContent", ChildSide, contentParentFilter));
2626
}
2727

2828
TEST(IPCLogging, CommaDelimitedProtocolsFilter)
2929
{
3030
const char* gmpContentFilter = "PGMPContentChild,PGMPContentParent";
31-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentChild", gmpContentFilter));
32-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentParent", gmpContentFilter));
33-
EXPECT_FALSE(LoggingEnabledFor("PContentParent", gmpContentFilter));
34-
EXPECT_FALSE(LoggingEnabledFor("PContentChild", gmpContentFilter));
31+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ChildSide, gmpContentFilter));
32+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ParentSide, gmpContentFilter));
33+
EXPECT_FALSE(LoggingEnabledFor("PContent", ParentSide, gmpContentFilter));
34+
EXPECT_FALSE(LoggingEnabledFor("PContent", ChildSide, gmpContentFilter));
3535
}
3636

3737
TEST(IPCLogging, SpaceDelimitedProtocolsFilter)
3838
{
3939
const char* gmpContentFilter = "PGMPContentChild PGMPContentParent";
40-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentChild", gmpContentFilter));
41-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentParent", gmpContentFilter));
42-
EXPECT_FALSE(LoggingEnabledFor("PContentParent", gmpContentFilter));
43-
EXPECT_FALSE(LoggingEnabledFor("PContentChild", gmpContentFilter));
40+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ChildSide, gmpContentFilter));
41+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ParentSide, gmpContentFilter));
42+
EXPECT_FALSE(LoggingEnabledFor("PContent", ParentSide, gmpContentFilter));
43+
EXPECT_FALSE(LoggingEnabledFor("PContent", ChildSide, gmpContentFilter));
4444
}
4545

4646
TEST(IPCLogging, CatchAllFilter)
4747
{
4848
const char* catchAllFilter = "1";
49-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentChild", catchAllFilter));
50-
EXPECT_TRUE(LoggingEnabledFor("PGMPContentParent", catchAllFilter));
51-
EXPECT_TRUE(LoggingEnabledFor("PContentParent", catchAllFilter));
52-
EXPECT_TRUE(LoggingEnabledFor("PContentChild", catchAllFilter));
49+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ChildSide, catchAllFilter));
50+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ParentSide, catchAllFilter));
51+
EXPECT_TRUE(LoggingEnabledFor("PContent", ParentSide, catchAllFilter));
52+
EXPECT_TRUE(LoggingEnabledFor("PContent", ChildSide, catchAllFilter));
53+
}
54+
55+
TEST(IPCLogging, BothSidesFilter)
56+
{
57+
const char* gmpContentFilter = "PGMPContent,PContentParent";
58+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ChildSide, gmpContentFilter));
59+
EXPECT_TRUE(LoggingEnabledFor("PGMPContent", ParentSide, gmpContentFilter));
60+
EXPECT_TRUE(LoggingEnabledFor("PContent", ParentSide, gmpContentFilter));
61+
EXPECT_FALSE(LoggingEnabledFor("PContent", ChildSide, gmpContentFilter));
5362
}
5463
#endif // defined(DEBUG) || defined(FUZZING)
5564

ipc/ipdl/ipdl/lower.py

+8-13
Original file line numberDiff line numberDiff line change
@@ -363,18 +363,6 @@ def _otherSide(side):
363363
assert 0
364364

365365

366-
def _ifLogging(topLevelProtocol, stmts):
367-
return StmtCode(
368-
"""
369-
if (mozilla::ipc::LoggingEnabledFor(${proto})) {
370-
$*{stmts}
371-
}
372-
""",
373-
proto=topLevelProtocol,
374-
stmts=stmts,
375-
)
376-
377-
378366
# XXX we need to remove these and install proper error handling
379367

380368

@@ -5582,9 +5570,14 @@ def makeSendMethodDecl(self, md, promise=False, paramsems="in"):
55825570

55835571
def logMessage(self, md, msgptr, pfx, actor=None, receiving=False):
55845572
actorname = _actorName(self.protocol.name, self.side)
5573+
if self.side == "parent":
5574+
side = ExprVar("mozilla::ipc::ParentSide")
5575+
else:
5576+
side = ExprVar("mozilla::ipc::ChildSide")
5577+
55855578
return StmtCode(
55865579
"""
5587-
if (mozilla::ipc::LoggingEnabledFor(${actorname})) {
5580+
if (mozilla::ipc::LoggingEnabledFor(${protocolname}, ${side})) {
55885581
mozilla::ipc::LogMessageForProtocol(
55895582
${actorname},
55905583
${actor}->ToplevelProtocol()->OtherPidMaybeInvalid(),
@@ -5593,6 +5586,8 @@ def logMessage(self, md, msgptr, pfx, actor=None, receiving=False):
55935586
mozilla::ipc::MessageDirection::${direction});
55945587
}
55955588
""",
5589+
protocolname=ExprLiteral.String(self.protocol.name),
5590+
side=side,
55965591
actorname=ExprLiteral.String(actorname),
55975592
actor=actor or ExprVar.THIS,
55985593
pfx=ExprLiteral.String(pfx),

0 commit comments

Comments
 (0)