aboutsummaryrefslogtreecommitdiff
path: root/src/tracing/ipc/service/service_ipc_host_impl.cc
blob: 1df674ef72ad7aa2b8be6e8786d53ae74ff1628d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/tracing/ipc/service/service_ipc_host_impl.h"

#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/ipc/host.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
#include "src/tracing/ipc/service/consumer_ipc_service.h"
#include "src/tracing/ipc/service/producer_ipc_service.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include "src/tracing/ipc/shared_memory_windows.h"
#else
#include "src/tracing/ipc/posix_shared_memory.h"
#endif

namespace perfetto {

namespace {
constexpr uint32_t kProducerSocketTxTimeoutMs = 10;
}

// TODO(fmayer): implement per-uid connection limit (b/69093705).

// Implements the publicly exposed factory method declared in
// include/tracing/posix_ipc/posix_service_host.h.
std::unique_ptr<ServiceIPCHost> ServiceIPCHost::CreateInstance(
    base::TaskRunner* task_runner,
    TracingService::InitOpts init_opts) {
  return std::unique_ptr<ServiceIPCHost>(
      new ServiceIPCHostImpl(task_runner, init_opts));
}

ServiceIPCHostImpl::ServiceIPCHostImpl(base::TaskRunner* task_runner,
                                       TracingService::InitOpts init_opts)
    : task_runner_(task_runner), init_opts_(init_opts) {}

ServiceIPCHostImpl::~ServiceIPCHostImpl() {}

bool ServiceIPCHostImpl::Start(const char* producer_socket_name,
                               const char* consumer_socket_name) {
  PERFETTO_CHECK(!svc_);  // Check if already started.

  // Initialize the IPC transport.
  producer_ipc_port_ =
      ipc::Host::CreateInstance(producer_socket_name, task_runner_);
  consumer_ipc_port_ =
      ipc::Host::CreateInstance(consumer_socket_name, task_runner_);
  return DoStart();
}

bool ServiceIPCHostImpl::Start(base::ScopedSocketHandle producer_socket_fd,
                               base::ScopedSocketHandle consumer_socket_fd) {
  PERFETTO_CHECK(!svc_);  // Check if already started.

  // Initialize the IPC transport.
  producer_ipc_port_ =
      ipc::Host::CreateInstance(std::move(producer_socket_fd), task_runner_);
  consumer_ipc_port_ =
      ipc::Host::CreateInstance(std::move(consumer_socket_fd), task_runner_);
  return DoStart();
}

bool ServiceIPCHostImpl::Start(std::unique_ptr<ipc::Host> producer_host,
                               std::unique_ptr<ipc::Host> consumer_host) {
  PERFETTO_CHECK(!svc_);  // Check if already started.
  PERFETTO_DCHECK(producer_host);
  PERFETTO_DCHECK(consumer_host);

  // Initialize the IPC transport.
  producer_ipc_port_ = std::move(producer_host);
  consumer_ipc_port_ = std::move(consumer_host);

  return DoStart();
}

bool ServiceIPCHostImpl::DoStart() {
  // Create and initialize the platform-independent tracing business logic.
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  std::unique_ptr<SharedMemory::Factory> shm_factory(
      new SharedMemoryWindows::Factory());
#else
  std::unique_ptr<SharedMemory::Factory> shm_factory(
      new PosixSharedMemory::Factory());
#endif
  svc_ = TracingService::CreateInstance(std::move(shm_factory), task_runner_,
                                        init_opts_);

  if (!producer_ipc_port_ || !consumer_ipc_port_) {
    Shutdown();
    return false;
  }

  // Lower the timeout for blocking socket sends to producers as we shouldn't
  // normally exhaust the kernel send buffer unless the producer is
  // unresponsive. We'll drop the connection if the timeout is hit (see
  // UnixSocket::Send). Context in b/236813972, b/193234818.
  // Consumer port continues using the default timeout (10s) as there are
  // generally fewer consumer processes, and they're better behaved. Also the
  // consumer port ipcs might exhaust the send buffer under normal operation
  // due to large messages such as ReadBuffersResponse.
  producer_ipc_port_->SetSocketSendTimeoutMs(kProducerSocketTxTimeoutMs);

  // TODO(fmayer): add a test that destroyes the ServiceIPCHostImpl soon after
  // Start() and checks that no spurious callbacks are issued.
  bool producer_service_exposed = producer_ipc_port_->ExposeService(
      std::unique_ptr<ipc::Service>(new ProducerIPCService(svc_.get())));
  PERFETTO_CHECK(producer_service_exposed);

  bool consumer_service_exposed = consumer_ipc_port_->ExposeService(
      std::unique_ptr<ipc::Service>(new ConsumerIPCService(svc_.get())));
  PERFETTO_CHECK(consumer_service_exposed);

  return true;
}

TracingService* ServiceIPCHostImpl::service() const {
  return svc_.get();
}

void ServiceIPCHostImpl::Shutdown() {
  // TODO(primiano): add a test that causes the Shutdown() and checks that no
  // spurious callbacks are issued.
  producer_ipc_port_.reset();
  consumer_ipc_port_.reset();
  svc_.reset();
}

// Definitions for the base class ctor/dtor.
ServiceIPCHost::ServiceIPCHost() = default;
ServiceIPCHost::~ServiceIPCHost() = default;

}  // namespace perfetto