Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include <signal.h>
7 : #include <stdio.h>
8 : #include <unistd.h>
9 : #include "mozilla/CodeCoverageHandler.h"
10 : #include "mozilla/ClearOnShutdown.h"
11 : #include "nsAppRunner.h"
12 :
13 : using namespace mozilla;
14 : using namespace mozilla::ipc;
15 :
16 : // The __gcov_dump function writes the coverage counters to gcda files.
17 : // The __gcov_reset function resets the coverage counters to zero.
18 : // They are defined at https://github.com/gcc-mirror/gcc/blob/aad93da1a579b9ae23ede6b9cf8523360f0a08b4/libgcc/libgcov-interface.c
19 : // __gcov_flush is protected by a mutex, __gcov_dump and __gcov_reset aren't.
20 : // So we are using a CrossProcessMutex to protect them.
21 :
22 : extern "C" void __gcov_dump();
23 : extern "C" void __gcov_reset();
24 :
25 3 : StaticAutoPtr<CodeCoverageHandler> CodeCoverageHandler::instance;
26 :
27 3 : void CodeCoverageHandler::DumpCounters(int)
28 : {
29 3 : CrossProcessMutexAutoLock lock(*CodeCoverageHandler::Get()->GetMutex());
30 :
31 3 : printf_stderr("[CodeCoverage] Requested dump.\n");
32 3 : __gcov_dump();
33 0 : printf_stderr("[CodeCoverage] Dump completed.\n");
34 0 : }
35 :
36 0 : void CodeCoverageHandler::ResetCounters(int)
37 : {
38 0 : CrossProcessMutexAutoLock lock(*CodeCoverageHandler::Get()->GetMutex());
39 :
40 0 : printf_stderr("[CodeCoverage] Requested reset.\n");
41 0 : __gcov_reset();
42 0 : printf_stderr("[CodeCoverage] Reset completed.\n");
43 0 : }
44 :
45 3 : void CodeCoverageHandler::SetSignalHandlers()
46 : {
47 3 : printf_stderr("[CodeCoverage] Setting handlers for process %d.\n", getpid());
48 :
49 : struct sigaction dump_sa;
50 3 : dump_sa.sa_handler = CodeCoverageHandler::DumpCounters;
51 3 : dump_sa.sa_flags = SA_RESTART;
52 3 : sigemptyset(&dump_sa.sa_mask);
53 3 : MOZ_ASSERT(sigaction(SIGUSR1, &dump_sa, nullptr) == 0);
54 :
55 : struct sigaction reset_sa;
56 3 : reset_sa.sa_handler = CodeCoverageHandler::ResetCounters;
57 3 : reset_sa.sa_flags = SA_RESTART;
58 3 : sigemptyset(&reset_sa.sa_mask);
59 3 : MOZ_ASSERT(sigaction(SIGUSR2, &reset_sa, nullptr) == 0);
60 3 : }
61 :
62 1 : CodeCoverageHandler::CodeCoverageHandler()
63 1 : : mGcovLock("GcovLock")
64 : {
65 1 : SetSignalHandlers();
66 1 : }
67 :
68 2 : CodeCoverageHandler::CodeCoverageHandler(const CrossProcessMutexHandle& aHandle)
69 2 : : mGcovLock(aHandle)
70 : {
71 2 : SetSignalHandlers();
72 2 : }
73 :
74 1 : void CodeCoverageHandler::Init()
75 : {
76 1 : MOZ_ASSERT(!instance);
77 1 : MOZ_ASSERT(XRE_IsParentProcess());
78 1 : instance = new CodeCoverageHandler();
79 1 : ClearOnShutdown(&instance);
80 1 : }
81 :
82 2 : void CodeCoverageHandler::Init(const CrossProcessMutexHandle& aHandle)
83 : {
84 2 : MOZ_ASSERT(!instance);
85 2 : MOZ_ASSERT(!XRE_IsParentProcess());
86 2 : instance = new CodeCoverageHandler(aHandle);
87 2 : ClearOnShutdown(&instance);
88 2 : }
89 :
90 5 : CodeCoverageHandler* CodeCoverageHandler::Get()
91 : {
92 5 : MOZ_ASSERT(instance);
93 5 : return instance;
94 : }
95 :
96 3 : CrossProcessMutex* CodeCoverageHandler::GetMutex()
97 : {
98 3 : return &mGcovLock;
99 : }
100 :
101 2 : CrossProcessMutexHandle CodeCoverageHandler::GetMutexHandle(int aProcId)
102 : {
103 2 : return mGcovLock.ShareToProcess(aProcId);
104 9 : }
|