Skip to content

Commit

Permalink
Improve support for applications that rely on fork for parallelism
Browse files Browse the repository at this point in the history
A forked process inherits the elfmap of the parent, thus we need to
copy that data when we encounter a fork event. To do so reliably,
we need to flush the event buffer, as otherwise the mmmap state may
not be accurate.

Furthermore, pass the ppid through the ThreadStart event, to allow
client applications to inherit the comm for the newly created process.

Fixes: KDAB/hotspot#241
Change-Id: I5de13644e12def6704c5f622428a815fd87d2af4
  • Loading branch information
milianw committed Jun 12, 2020
1 parent c3be6e3 commit 93f77ae
Show file tree
Hide file tree
Showing 10 changed files with 7,560 additions and 2 deletions.
2 changes: 2 additions & 0 deletions app/perfdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@ class PerfRecordFork : public PerfRecord
bool sampleIdAll = false);
qint32 childTid() const { return m_tid; }
qint32 childPid() const { return m_pid; }
qint32 parentTid() const { return m_ptid; }
qint32 parentPid() const { return m_ppid; }
private:
qint32 m_pid, m_ppid;
qint32 m_tid, m_ptid;
Expand Down
6 changes: 6 additions & 0 deletions app/perfelfmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ class PerfElfMap : public QObject

bool isAddressInRange(quint64 addr) const;

void copyDataFrom(const PerfElfMap *parent)
{
m_elfs = parent->m_elfs;
m_lastBase = parent->m_lastBase;
}

signals:
void aboutToInvalidate(const ElfInfo &elf);

Expand Down
5 changes: 5 additions & 0 deletions app/perfsymboltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,3 +1175,8 @@ PerfSymbolTable::ElfAndFile::ElfAndFile(PerfSymbolTable::ElfAndFile &&other)
other.m_elf = nullptr;
other.m_file = -1;
}

void PerfSymbolTable::initAfterFork(const PerfSymbolTable* parent)
{
m_elfs.copyDataFrom(&parent->m_elfs);
}
2 changes: 2 additions & 0 deletions app/perfsymboltable.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class PerfSymbolTable
void clearCache();
bool cacheIsDirty() const { return m_cacheIsDirty; }

void initAfterFork(const PerfSymbolTable *parent);

private:
// Report an mmap to dwfl and parse it for symbols and inlines, or simply return it if dwfl has
// it already
Expand Down
11 changes: 9 additions & 2 deletions app/perfunwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,15 @@ void PerfUnwind::analyze(const PerfRecordSample &sample)
void PerfUnwind::fork(const PerfRecordFork &sample)
{
bufferEvent(TaskEvent{sample.childPid(), sample.childTid(), sample.time(), sample.cpu(),
0, ThreadStart},
sample.parentPid(), ThreadStart},
&m_taskEventsBuffer, &m_stats.numTaskEventsInRound);

if (sample.childPid() != sample.parentPid()) {
// we need to flush to ensure the parent symbol table contains an accurate
// representation of the current elf mappings
flushEventBuffer(0);
symbolTable(sample.childPid())->initAfterFork(symbolTable(sample.parentPid()));
}
}

void PerfUnwind::exit(const PerfRecordExit &sample)
Expand Down Expand Up @@ -1034,7 +1041,7 @@ void PerfUnwind::sendTaskEvent(const TaskEvent& taskEvent)

if (taskEvent.m_type == ContextSwitchDefinition)
stream << static_cast<bool>(taskEvent.m_payload);
else if (taskEvent.m_type == Command)
else if (taskEvent.m_type == Command || taskEvent.m_type == ThreadStart)
stream << taskEvent.m_payload;

sendBuffer(buffer);
Expand Down
Binary file added tests/auto/perfdata/fork_static_gcc/fork
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 93f77ae

Please sign in to comment.