Minor changes to IPC layer in preparation for Win port.
This CL doesn't introduce any major change (neither on
Windows nor on Linux). It mainly refactor the codebase
to make the Windows IPC cls easier to review:
- Rename the GN target platform_posix to platform_impl
(Soon the same target will have a platform_windows.cc)
- Add a platform_unittest to cover the platform TLS logic.
- Refactor ThreadTaskRunner to directly expose a TaskRunner
interface (soon platform_windows.cc will need it as well).
- Refactor a bunch of places to take a ScopedSocketHandle
rather than a ScopedFile. They are the same type on POSIX
but not on Windows (where the latter wraps a SOCKET).
- Remove the fd() argument from the base SharedMemory class.
That makes sense only on POSIX and it caused a lot of empty
implementation around (note: this will cause a Chromium
roll failure, we need to match the removal in .MojoSharedMemory)
- Minor other tweaks to get rid of platform-specific includes.
Bug: 174454879
Test: manual on Windows.
Change-Id: Iead1ec87213c56fd3bb170c72d482f71fa33e7e3
diff --git a/Android.bp b/Android.bp
index d2eefc3..f520c93 100644
--- a/Android.bp
+++ b/Android.bp
@@ -715,7 +715,7 @@
":perfetto_src_tracing_ipc_consumer_consumer",
":perfetto_src_tracing_ipc_producer_producer",
":perfetto_src_tracing_ipc_service_service",
- ":perfetto_src_tracing_platform_posix",
+ ":perfetto_src_tracing_platform_impl",
":perfetto_src_tracing_system_backend",
],
shared_libs: [
@@ -1731,7 +1731,7 @@
":perfetto_src_tracing_ipc_consumer_consumer",
":perfetto_src_tracing_ipc_producer_producer",
":perfetto_src_tracing_ipc_service_service",
- ":perfetto_src_tracing_platform_posix",
+ ":perfetto_src_tracing_platform_impl",
":perfetto_src_tracing_system_backend",
":perfetto_src_tracing_test_api_test_support",
":perfetto_src_tracing_test_client_api_integrationtests",
@@ -8283,9 +8283,9 @@
],
}
-// GN: //src/tracing:platform_posix
+// GN: //src/tracing:platform_impl
filegroup {
- name: "perfetto_src_tracing_platform_posix",
+ name: "perfetto_src_tracing_platform_impl",
srcs: [
"src/tracing/platform_posix.cc",
],
@@ -8333,6 +8333,7 @@
filegroup {
name: "perfetto_src_tracing_test_tracing_integration_test",
srcs: [
+ "src/tracing/test/platform_unittest.cc",
"src/tracing/test/tracing_integration_test.cc",
],
}
@@ -8707,6 +8708,7 @@
":perfetto_src_traced_probes_unittests",
":perfetto_src_traced_service_service",
":perfetto_src_traced_service_unittests",
+ ":perfetto_src_tracing_client_api_without_backends",
":perfetto_src_tracing_common",
":perfetto_src_tracing_core_core",
":perfetto_src_tracing_core_service",
@@ -8717,6 +8719,7 @@
":perfetto_src_tracing_ipc_producer_producer",
":perfetto_src_tracing_ipc_service_service",
":perfetto_src_tracing_ipc_unittests",
+ ":perfetto_src_tracing_platform_impl",
":perfetto_src_tracing_test_test_support",
":perfetto_src_tracing_test_tracing_integration_test",
":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
diff --git a/BUILD b/BUILD
index 20db6b0..2579427 100644
--- a/BUILD
+++ b/BUILD
@@ -1595,9 +1595,9 @@
],
)
-# GN target: //src/tracing:platform_posix
+# GN target: //src/tracing:platform_impl
filegroup(
- name = "src_tracing_platform_posix",
+ name = "src_tracing_platform_impl",
srcs = [
"src/tracing/platform_posix.cc",
],
@@ -3057,7 +3057,7 @@
":src_tracing_ipc_consumer_consumer",
":src_tracing_ipc_producer_producer",
":src_tracing_ipc_service_service",
- ":src_tracing_platform_posix",
+ ":src_tracing_platform_impl",
":src_tracing_system_backend",
],
hdrs = [
diff --git a/BUILD.gn b/BUILD.gn
index 92f81ce..c6e6717 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -233,7 +233,7 @@
public_deps = [
"gn:default_deps",
"src/tracing:client_api",
- "src/tracing:platform_posix",
+ "src/tracing:platform_impl",
]
sources = [ "include/perfetto/tracing.h" ]
assert_no_deps = [ "//gn:protobuf_lite" ]
diff --git a/include/perfetto/ext/base/thread_task_runner.h b/include/perfetto/ext/base/thread_task_runner.h
index 6579fa5..d4e672e 100644
--- a/include/perfetto/ext/base/thread_task_runner.h
+++ b/include/perfetto/ext/base/thread_task_runner.h
@@ -32,7 +32,7 @@
// * the UnixTaskRunner will be constructed and destructed on the task thread.
// * the task thread will live for the lifetime of the UnixTaskRunner.
//
-class ThreadTaskRunner {
+class ThreadTaskRunner : public TaskRunner {
public:
static ThreadTaskRunner CreateAndStart(const std::string& name = "") {
return ThreadTaskRunner(name);
@@ -43,7 +43,7 @@
ThreadTaskRunner(ThreadTaskRunner&&) noexcept;
ThreadTaskRunner& operator=(ThreadTaskRunner&&);
- ~ThreadTaskRunner();
+ ~ThreadTaskRunner() override;
// Executes the given function on the task runner thread and blocks the caller
// thread until the function has run.
@@ -62,6 +62,14 @@
// should be handled exclusively by this class' destructor.
UnixTaskRunner* get() const { return task_runner_; }
+ // TaskRunner implementation.
+ // These methods just proxy to the underlying task_runner_.
+ void PostTask(std::function<void()>) override;
+ void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
+ void AddFileDescriptorWatch(PlatformHandle, std::function<void()>) override;
+ void RemoveFileDescriptorWatch(PlatformHandle) override;
+ bool RunsTasksOnCurrentThread() const override;
+
private:
explicit ThreadTaskRunner(const std::string& name);
void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
diff --git a/include/perfetto/ext/base/utils.h b/include/perfetto/ext/base/utils.h
index 0ec629d..a680b5c 100644
--- a/include/perfetto/ext/base/utils.h
+++ b/include/perfetto/ext/base/utils.h
@@ -114,6 +114,7 @@
// around various Scudo inefficiencies. See b/170217718.
void MaybeReleaseAllocatorMemToOS();
+// geteuid() on POSIX OSes, returns 0 on Windows (See comment in utils.cc).
uid_t GetCurrentUserId();
} // namespace base
diff --git a/include/perfetto/ext/ipc/basic_types.h b/include/perfetto/ext/ipc/basic_types.h
index 7d99c26..6442097 100644
--- a/include/perfetto/ext/ipc/basic_types.h
+++ b/include/perfetto/ext/ipc/basic_types.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/cpp_message_obj.h"
namespace perfetto {
diff --git a/include/perfetto/ext/ipc/client.h b/include/perfetto/ext/ipc/client.h
index 39e8bec..d04ac85 100644
--- a/include/perfetto/ext/ipc/client.h
+++ b/include/perfetto/ext/ipc/client.h
@@ -21,6 +21,7 @@
#include <memory>
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/ipc/basic_types.h"
@@ -51,14 +52,14 @@
struct ConnArgs {
ConnArgs(const char* sock_name, bool sock_retry)
: socket_name(sock_name), retry(sock_retry) {}
- explicit ConnArgs(base::ScopedFile sock_fd)
+ explicit ConnArgs(base::ScopedSocketHandle sock_fd)
: socket_fd(std::move(sock_fd)) {}
// Disallow copy. Only supports move.
ConnArgs(const ConnArgs& other) = delete;
ConnArgs(ConnArgs&& other) = default;
- base::ScopedFile socket_fd;
+ base::ScopedSocketHandle socket_fd;
const char* socket_name = nullptr;
bool retry = false; // Only for connecting with |socket_name|.
};
diff --git a/include/perfetto/ext/ipc/client_info.h b/include/perfetto/ext/ipc/client_info.h
index 0b43f9a..6988d18 100644
--- a/include/perfetto/ext/ipc/client_info.h
+++ b/include/perfetto/ext/ipc/client_info.h
@@ -17,9 +17,8 @@
#ifndef INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
-#include <unistd.h>
-
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/ipc/basic_types.h"
namespace perfetto {
diff --git a/include/perfetto/ext/ipc/host.h b/include/perfetto/ext/ipc/host.h
index bbf3657..a9b5824 100644
--- a/include/perfetto/ext/ipc/host.h
+++ b/include/perfetto/ext/ipc/host.h
@@ -20,6 +20,7 @@
#include <memory>
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/ipc/basic_types.h"
namespace perfetto {
@@ -45,7 +46,7 @@
// Like the above but takes a file descriptor to a pre-bound unix socket.
// Returns nullptr if listening on the socket fails.
- static std::unique_ptr<Host> CreateInstance(base::ScopedFile socket_fd,
+ static std::unique_ptr<Host> CreateInstance(base::ScopedSocketHandle,
base::TaskRunner*);
virtual ~Host();
diff --git a/include/perfetto/ext/tracing/core/shared_memory.h b/include/perfetto/ext/tracing/core/shared_memory.h
index 11d078a..b1bcbcb 100644
--- a/include/perfetto/ext/tracing/core/shared_memory.h
+++ b/include/perfetto/ext/tracing/core/shared_memory.h
@@ -22,6 +22,7 @@
#include <memory>
#include "perfetto/base/export.h"
+#include "perfetto/base/platform_handle.h"
namespace perfetto {
@@ -46,7 +47,6 @@
virtual void* start() const = 0;
virtual size_t size() const = 0;
- virtual int fd() const = 0;
};
} // namespace perfetto
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
index ed3deb9..567851d 100644
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
@@ -21,6 +21,7 @@
#include "perfetto/base/export.h"
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/tracing/core/basic_types.h"
namespace perfetto {
@@ -48,8 +49,8 @@
// Like the above, but takes two file descriptors to already bound sockets.
// This is used when building as part of the Android tree, where init opens
// and binds the socket beore exec()-ing us.
- virtual bool Start(base::ScopedFile producer_socket_fd,
- base::ScopedFile consumer_socket_fd) = 0;
+ virtual bool Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) = 0;
virtual TracingService* service() const = 0;
diff --git a/src/base/thread_task_runner.cc b/src/base/thread_task_runner.cc
index 7f8b670..08e3cea 100644
--- a/src/base/thread_task_runner.cc
+++ b/src/base/thread_task_runner.cc
@@ -114,5 +114,28 @@
return thread_time_ns;
}
+void ThreadTaskRunner::PostTask(std::function<void()> task) {
+ task_runner_->PostTask(std::move(task));
+}
+
+void ThreadTaskRunner::PostDelayedTask(std::function<void()> task,
+ uint32_t delay_ms) {
+ task_runner_->PostDelayedTask(std::move(task), delay_ms);
+}
+
+void ThreadTaskRunner::AddFileDescriptorWatch(
+ PlatformHandle handle,
+ std::function<void()> watch_task) {
+ task_runner_->AddFileDescriptorWatch(handle, std::move(watch_task));
+}
+
+void ThreadTaskRunner::RemoveFileDescriptorWatch(PlatformHandle handle) {
+ task_runner_->RemoveFileDescriptorWatch(handle);
+}
+
+bool ThreadTaskRunner::RunsTasksOnCurrentThread() const {
+ return task_runner_->RunsTasksOnCurrentThread();
+}
+
} // namespace base
} // namespace perfetto
diff --git a/src/base/utils.cc b/src/base/utils.cc
index 1f66a38..0e15bf6 100644
--- a/src/base/utils.cc
+++ b/src/base/utils.cc
@@ -17,11 +17,15 @@
#include "perfetto/ext/base/utils.h"
#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <unistd.h> // For getpagesize().
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#include <unistd.h> // For getpagesize() and geteuid().
+#endif
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#include <mach/vm_page_size.h>
#endif
@@ -82,5 +86,27 @@
#endif
}
+uid_t GetCurrentUserId() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ return geteuid();
+#else
+ // TODO(primiano): On Windows we could hash the current user SID and derive a
+ // numeric user id [1]. It is not clear whether we need that. Right now that
+ // would not bring any benefit. Returning 0 unil we can prove we need it.
+ // [1]:https://android-review.googlesource.com/c/platform/external/perfetto/+/1513879/25/src/base/utils.cc
+ return 0;
+#endif
+}
+
+void SetEnv(const std::string& key, const std::string& value) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_CHECK(::_putenv_s(key.c_str(), value.c_str()) == 0);
+#else
+ PERFETTO_CHECK(::setenv(key.c_str(), value.c_str(), /*overwrite=*/true) == 0);
+#endif
+}
+
} // namespace base
} // namespace perfetto
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index 26106b1..c27bf37 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -18,7 +18,6 @@
#include <fcntl.h>
#include <inttypes.h>
-#include <unistd.h>
#include <utility>
@@ -198,12 +197,16 @@
auto buf = frame_deserializer_.BeginReceive();
base::ScopedFile fd;
rsize = sock_->Receive(buf.data, buf.size, &fd);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ PERFETTO_DCHECK(!fd);
+#else
if (fd) {
PERFETTO_DCHECK(!received_fd_);
int res = fcntl(*fd, F_SETFD, FD_CLOEXEC);
PERFETTO_DCHECK(res == 0);
received_fd_ = std::move(fd);
}
+#endif
if (!frame_deserializer_.EndReceive(rsize)) {
// The endpoint tried to send a frame that is way too large.
return sock_->Shutdown(true); // In turn will trigger an OnDisconnect().
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index 8fe9346..c482e1e 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -340,6 +340,8 @@
ASSERT_EQ(kNumReplies, replies_seen);
}
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// File descriptor sending over IPC is not supported on Windows.
TEST_F(ClientImplTest, ReceiveFileDescriptor) {
auto* host_svc = host_->AddFakeService("FakeSvc");
auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
@@ -429,6 +431,7 @@
PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
ASSERT_STREQ(kFileContent, buf);
}
+#endif // !OS_WIN
TEST_F(ClientImplTest, BindSameServiceMultipleTimesShouldFail) {
host_->AddFakeService("FakeSvc");
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index 62b9910..0b5038c 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -55,7 +55,7 @@
}
// static
-std::unique_ptr<Host> Host::CreateInstance(base::ScopedFile socket_fd,
+std::unique_ptr<Host> Host::CreateInstance(base::ScopedSocketHandle socket_fd,
base::TaskRunner* task_runner) {
std::unique_ptr<HostImpl> host(
new HostImpl(std::move(socket_fd), task_runner));
@@ -64,7 +64,8 @@
return std::unique_ptr<Host>(std::move(host));
}
-HostImpl::HostImpl(base::ScopedFile socket_fd, base::TaskRunner* task_runner)
+HostImpl::HostImpl(base::ScopedSocketHandle socket_fd,
+ base::TaskRunner* task_runner)
: task_runner_(task_runner), weak_ptr_factory_(this) {
PERFETTO_DCHECK_THREAD(thread_checker_);
sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_,
diff --git a/src/ipc/host_impl.h b/src/ipc/host_impl.h
index 7b12d9f..ac0a593 100644
--- a/src/ipc/host_impl.h
+++ b/src/ipc/host_impl.h
@@ -35,7 +35,7 @@
class HostImpl : public Host, public base::UnixSocket::EventListener {
public:
HostImpl(const char* socket_name, base::TaskRunner*);
- HostImpl(base::ScopedFile socket_fd, base::TaskRunner*);
+ HostImpl(base::ScopedSocketHandle, base::TaskRunner*);
~HostImpl() override;
// Host implementation.
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index d030a02..13147a7 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -320,6 +320,8 @@
task_runner_->RunUntilCheckpoint("on_reply_received");
}
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// File descriptor sending over IPC is not supported on Windows.
TEST_F(HostImplTest, SendFileDescriptor) {
FakeService* fake_service = new FakeService("FakeService");
ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
@@ -398,6 +400,7 @@
PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
ASSERT_STREQ(kFileContent, buf);
}
+#endif // !OS_WIN
// Invoke a method and immediately after disconnect the client.
TEST_F(HostImplTest, OnClientDisconnect) {
diff --git a/src/traced/service/builtin_producer.cc b/src/traced/service/builtin_producer.cc
index 8538c00..6987c79 100644
--- a/src/traced/service/builtin_producer.cc
+++ b/src/traced/service/builtin_producer.cc
@@ -17,11 +17,11 @@
#include "src/traced/service/builtin_producer.h"
#include <sys/types.h>
-#include <unistd.h>
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/metatrace.h"
+#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
@@ -62,7 +62,7 @@
void BuiltinProducer::ConnectInProcess(TracingService* svc) {
endpoint_ = svc->ConnectProducer(
- this, geteuid(), "traced",
+ this, base::GetCurrentUserId(), "traced",
/*shared_memory_size_hint_bytes=*/16 * 1024, /*in_process=*/true,
TracingService::ProducerSMBScrapingMode::kDisabled,
/*shmem_page_size_hint_bytes=*/4096);
diff --git a/src/traced/service/service.cc b/src/traced/service/service.cc
index 769ce05..4881b75 100644
--- a/src/traced/service/service.cc
+++ b/src/traced/service/service.cc
@@ -156,8 +156,8 @@
started = svc->Start(std::move(producer_fd), std::move(consumer_fd));
#endif
} else {
- unlink(GetProducerSocket());
- unlink(GetConsumerSocket());
+ remove(GetProducerSocket());
+ remove(GetConsumerSocket());
started = svc->Start(GetProducerSocket(), GetConsumerSocket());
if (!producer_socket_group.empty()) {
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 8588bf1..b43466f 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -51,15 +51,13 @@
}
# Separate target because the embedder might not want this (e.g. on Windows).
-if (is_linux || is_mac || is_android) {
- source_set("platform_posix") {
- deps = [
- "../../gn:default_deps",
- "../../include/perfetto/tracing",
- "../base",
- ]
- sources = [ "platform_posix.cc" ]
- }
+source_set("platform_impl") {
+ deps = [
+ "../../gn:default_deps",
+ "../../include/perfetto/tracing",
+ "../base",
+ ]
+ sources = [ "platform_posix.cc" ]
}
# Fake platform that allows buiding the client lib on all OSes. You can only use
@@ -172,7 +170,7 @@
source_set("benchmarks") {
testonly = true
deps = [
- ":platform_posix",
+ ":platform_impl",
"../..:libperfetto_client_experimental",
"../../gn:benchmark",
"../../gn:default_deps",
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 8644a81..28ae872 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -17,8 +17,6 @@
#include "src/tracing/core/tracing_service_impl.h"
#include "perfetto/base/build_config.h"
-#include "perfetto/base/status.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
#include <errno.h>
#include <inttypes.h>
@@ -48,12 +46,14 @@
#include <algorithm>
#include "perfetto/base/build_config.h"
+#include "perfetto/base/status.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/watchdog.h"
+#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/observable_events.h"
#include "perfetto/ext/tracing/core/producer.h"
@@ -136,13 +136,6 @@
#define IOV_MAX 1024 // Linux compatible limit.
-// uid checking is a NOP on Windows.
-uid_t getuid() {
- return 0;
-}
-uid_t geteuid() {
- return 0;
-}
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
// PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
@@ -287,7 +280,7 @@
base::TaskRunner* task_runner)
: task_runner_(task_runner),
shm_factory_(std::move(shm_factory)),
- uid_(getuid()),
+ uid_(base::GetCurrentUserId()),
buffer_ids_(kMaxTraceBufferID),
weak_ptr_factory_(this) {
PERFETTO_DCHECK(task_runner_);
@@ -308,7 +301,7 @@
std::unique_ptr<SharedMemory> shm) {
PERFETTO_DCHECK_THREAD(thread_checker_);
- if (lockdown_mode_ && uid != geteuid()) {
+ if (lockdown_mode_ && uid != base::GetCurrentUserId()) {
PERFETTO_DLOG("Lockdown mode. Rejecting producer with UID %ld",
static_cast<unsigned long>(uid));
return nullptr;
@@ -2634,9 +2627,7 @@
static_cast<uint32_t>(clock.type),
static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count())));
}
-#else // !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) &&
- // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&
- // !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+#else // OS_APPLE || OS_WIN && OS_NACL
auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
// The default trace clock is boot time, so we always need to emit a path to
// it. However since we don't actually have a boot time source on these
@@ -2645,9 +2636,7 @@
std::make_pair(protos::pbzero::BUILTIN_CLOCK_BOOTTIME, wall_time_ns));
new_snapshot_data.push_back(
std::make_pair(protos::pbzero::BUILTIN_CLOCK_MONOTONIC, wall_time_ns));
-#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) &&
- // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&
- // !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+#endif
// If we're about to update a session's latest clock snapshot that hasn't been
// emitted into the trace yet, check whether the clocks have drifted enough to
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 2830045..f5ff1e0 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -1167,7 +1167,8 @@
consumer->Connect(svc.get());
std::unique_ptr<MockProducer> producer = CreateMockProducer();
- producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
+ producer->Connect(svc.get(), "mock_producer_sameuid",
+ base::GetCurrentUserId());
producer->RegisterDataSource("data_source");
TraceConfig trace_config;
@@ -1182,8 +1183,9 @@
producer->WaitForDataSourceStart("data_source");
std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
- auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
- "mock_producer_ouid");
+ auto x =
+ svc->ConnectProducer(producer_otheruid.get(),
+ base::GetCurrentUserId() + 1, "mock_producer_ouid");
EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
task_runner.RunUntilIdle();
Mock::VerifyAndClearExpectations(producer_otheruid.get());
@@ -1199,7 +1201,8 @@
producer->WaitForDataSourceStart("data_source");
std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
- producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
+ producer_otheruid->Connect(svc.get(), "mock_producer_ouid2",
+ base::GetCurrentUserId() + 1);
consumer->DisableTracing();
producer->WaitForDataSourceStop("data_source");
@@ -1549,7 +1552,7 @@
for (size_t i = 0; i < kNumProducers; i++) {
auto name = "mock_producer_" + std::to_string(i);
producer[i] = CreateMockProducer();
- producer[i]->Connect(svc.get(), name, geteuid(),
+ producer[i]->Connect(svc.get(), name, base::GetCurrentUserId(),
kSizes[i].hint_size_kb * 1024,
kSizes[i].hint_page_size_kb * 1024);
producer[i]->RegisterDataSource("data_source");
diff --git a/src/tracing/internal/in_process_tracing_backend.cc b/src/tracing/internal/in_process_tracing_backend.cc
index 378185c..1df0f4b 100644
--- a/src/tracing/internal/in_process_tracing_backend.cc
+++ b/src/tracing/internal/in_process_tracing_backend.cc
@@ -42,7 +42,6 @@
~InProcessShm() override;
void* start() const override;
size_t size() const override;
- int fd() const override;
private:
base::PagedMemory mem_;
@@ -67,10 +66,6 @@
return mem_.size();
}
-int InProcessShm::fd() const {
- return -1;
-}
-
InProcessShmFactory::~InProcessShmFactory() = default;
std::unique_ptr<SharedMemory> InProcessShmFactory::CreateSharedMemory(
size_t size) {
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index a627518..4130954 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -44,7 +44,9 @@
#include "protos/perfetto/config/interceptor_config.gen.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <io.h> // For dup()
+#else
#include <unistd.h> // For dup()
#endif
@@ -429,8 +431,9 @@
TracingMuxerImpl::TracingSessionImpl::TracingSessionImpl(
TracingMuxerImpl* muxer,
- TracingSessionGlobalID session_id)
- : muxer_(muxer), session_id_(session_id) {}
+ TracingSessionGlobalID session_id,
+ BackendType backend_type)
+ : muxer_(muxer), session_id_(session_id), backend_type_(backend_type) {}
// Can be destroyed from any thread.
TracingMuxerImpl::TracingSessionImpl::~TracingSessionImpl() {
@@ -447,14 +450,17 @@
auto session_id = session_id_;
std::shared_ptr<TraceConfig> trace_config(new TraceConfig(cfg));
if (fd >= 0) {
+ base::ignore_result(backend_type_); // For -Wunused in the amalgamation.
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
- PERFETTO_FATAL(
- "Passing a file descriptor to TracingSession::Setup() is not supported "
- "on Windows yet. Use TracingSession::ReadTrace() instead");
-#else
+ if (backend_type_ != kInProcessBackend) {
+ PERFETTO_FATAL(
+ "Passing a file descriptor to TracingSession::Setup() is only "
+ "supported with the kInProcessBackend on Windows. Use "
+ "TracingSession::ReadTrace() instead");
+ }
+#endif
trace_config->set_write_into_file(true);
fd = dup(fd);
-#endif
}
muxer->task_runner_->PostTask([muxer, session_id, trace_config, fd] {
muxer->SetupTracingSession(session_id, trace_config, base::ScopedFile(fd));
@@ -1454,7 +1460,7 @@
});
return std::unique_ptr<TracingSession>(
- new TracingSessionImpl(this, session_id));
+ new TracingSessionImpl(this, session_id, backend_type));
}
void TracingMuxerImpl::InitializeInstance(const TracingInitArgs& args) {
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
index d1fa4ee..0c97a60 100644
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ b/src/tracing/internal/tracing_muxer_impl.h
@@ -327,7 +327,7 @@
// Tracing::CreateTracingSession().
class TracingSessionImpl : public TracingSession {
public:
- TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID);
+ TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID, BackendType);
~TracingSessionImpl() override;
void Setup(const TraceConfig&, int fd) override;
void Start() override;
@@ -346,6 +346,7 @@
private:
TracingMuxerImpl* const muxer_;
TracingSessionGlobalID const session_id_;
+ BackendType const backend_type_;
};
struct RegisteredDataSource {
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index 59aeaaf..91a1d76 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -75,6 +75,14 @@
return;
}
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (fd) {
+ consumer_->OnTracingDisabled(
+ "Passing FDs for write_into_file is not supported on Windows");
+ return;
+ }
+#endif
+
protos::gen::EnableTracingRequest req;
*req.mutable_trace_config() = trace_config;
ipc::Deferred<protos::gen::EnableTracingResponse> async_response;
diff --git a/src/tracing/ipc/posix_shared_memory.cc b/src/tracing/ipc/posix_shared_memory.cc
index 5fc7982..3a59948 100644
--- a/src/tracing/ipc/posix_shared_memory.cc
+++ b/src/tracing/ipc/posix_shared_memory.cc
@@ -16,6 +16,10 @@
#include "src/tracing/ipc/posix_shared_memory.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
@@ -127,3 +131,5 @@
}
} // namespace perfetto
+
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/ipc/posix_shared_memory.h b/src/tracing/ipc/posix_shared_memory.h
index e637015..18c7dd7 100644
--- a/src/tracing/ipc/posix_shared_memory.h
+++ b/src/tracing/ipc/posix_shared_memory.h
@@ -17,6 +17,12 @@
#ifndef SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
#define SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
+#include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
#include <stddef.h>
#include <memory>
@@ -50,7 +56,7 @@
~PosixSharedMemory() override;
- int fd() const override { return fd_.get(); }
+ int fd() const { return fd_.get(); }
// SharedMemory implementation.
void* start() const override { return start_; }
@@ -70,4 +76,5 @@
} // namespace perfetto
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
#endif // SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
diff --git a/src/tracing/ipc/posix_shared_memory_unittest.cc b/src/tracing/ipc/posix_shared_memory_unittest.cc
index c9ab3e8..b3c5967 100644
--- a/src/tracing/ipc/posix_shared_memory_unittest.cc
+++ b/src/tracing/ipc/posix_shared_memory_unittest.cc
@@ -16,6 +16,10 @@
#include "src/tracing/ipc/posix_shared_memory.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -144,3 +148,4 @@
} // namespace
} // namespace perfetto
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index ebb9e01..64b1023 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -158,7 +158,7 @@
int shm_fd = -1;
if (shared_memory_) {
- shm_fd = shared_memory_->fd();
+ shm_fd = static_cast<PosixSharedMemory*>(shared_memory_.get())->fd();
req.set_producer_provided_shmem(true);
}
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.cc b/src/tracing/ipc/service/service_ipc_host_impl.cc
index ad6f9ef..d19fef6 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.cc
+++ b/src/tracing/ipc/service/service_ipc_host_impl.cc
@@ -52,8 +52,8 @@
return DoStart();
}
-bool ServiceIPCHostImpl::Start(base::ScopedFile producer_socket_fd,
- base::ScopedFile consumer_socket_fd) {
+bool ServiceIPCHostImpl::Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) {
PERFETTO_CHECK(!svc_); // Check if already started.
// Initialize the IPC transport.
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.h b/src/tracing/ipc/service/service_ipc_host_impl.h
index d06ef60..1aa73e1 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.h
+++ b/src/tracing/ipc/service/service_ipc_host_impl.h
@@ -39,8 +39,8 @@
// ServiceIPCHost implementation.
bool Start(const char* producer_socket_name,
const char* consumer_socket_name) override;
- bool Start(base::ScopedFile producer_socket_fd,
- base::ScopedFile consumer_socket_fd) override;
+ bool Start(base::ScopedSocketHandle producer_socket_fd,
+ base::ScopedSocketHandle consumer_socket_fd) override;
TracingService* service() const override;
diff --git a/src/tracing/platform_posix.cc b/src/tracing/platform_posix.cc
index 744b3bd..6b04aaf 100644
--- a/src/tracing/platform_posix.cc
+++ b/src/tracing/platform_posix.cc
@@ -15,6 +15,11 @@
*/
#include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/tracing/internal/tracing_tls.h"
@@ -42,23 +47,6 @@
pthread_key_t tls_key_{};
};
-// TODO(primiano): make base::ThreadTaskRunner directly inherit TaskRunner, so
-// we can avoid this boilerplate.
-class TaskRunnerInstance : public base::TaskRunner {
- public:
- TaskRunnerInstance();
- ~TaskRunnerInstance() override;
-
- void PostTask(std::function<void()>) override;
- void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
- void AddFileDescriptorWatch(int fd, std::function<void()>) override;
- void RemoveFileDescriptorWatch(int fd) override;
- bool RunsTasksOnCurrentThread() const override;
-
- private:
- base::ThreadTaskRunner thread_task_runner_;
-};
-
using ThreadLocalObject = Platform::ThreadLocalObject;
PlatformPosix::PlatformPosix() {
@@ -84,7 +72,8 @@
std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
const CreateTaskRunnerArgs&) {
- return std::unique_ptr<base::TaskRunner>(new TaskRunnerInstance());
+ return std::unique_ptr<base::TaskRunner>(
+ new base::ThreadTaskRunner(base::ThreadTaskRunner::CreateAndStart()));
}
std::string PlatformPosix::GetCurrentProcessName() {
@@ -100,31 +89,6 @@
#endif
}
-TaskRunnerInstance::TaskRunnerInstance()
- : thread_task_runner_(base::ThreadTaskRunner::CreateAndStart()) {}
-TaskRunnerInstance::~TaskRunnerInstance() = default;
-void TaskRunnerInstance::PostTask(std::function<void()> func) {
- thread_task_runner_.get()->PostTask(func);
-}
-
-void TaskRunnerInstance::PostDelayedTask(std::function<void()> func,
- uint32_t delay_ms) {
- thread_task_runner_.get()->PostDelayedTask(func, delay_ms);
-}
-
-void TaskRunnerInstance::AddFileDescriptorWatch(int fd,
- std::function<void()> func) {
- thread_task_runner_.get()->AddFileDescriptorWatch(fd, func);
-}
-
-void TaskRunnerInstance::RemoveFileDescriptorWatch(int fd) {
- thread_task_runner_.get()->RemoveFileDescriptorWatch(fd);
-}
-
-bool TaskRunnerInstance::RunsTasksOnCurrentThread() const {
- return thread_task_runner_.get()->RunsTasksOnCurrentThread();
-}
-
} // namespace
// static
@@ -134,3 +98,4 @@
}
} // namespace perfetto
+#endif // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/test/BUILD.gn b/src/tracing/test/BUILD.gn
index 442fe3c..0a4dc84 100644
--- a/src/tracing/test/BUILD.gn
+++ b/src/tracing/test/BUILD.gn
@@ -58,6 +58,8 @@
testonly = true
deps = [
":test_support",
+ "..:client_api_without_backends",
+ "..:platform_impl",
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
"../../base",
@@ -67,7 +69,10 @@
"../ipc/producer",
"../ipc/service",
]
- sources = [ "tracing_integration_test.cc" ]
+ sources = [
+ "platform_unittest.cc",
+ "tracing_integration_test.cc",
+ ]
}
}
@@ -77,7 +82,7 @@
deps = [
":api_test_support",
"../:client_api",
- "../:platform_posix",
+ "../:platform_impl",
"../../../:libperfetto_client_experimental",
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index aa9824e..8333b36 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -31,6 +31,10 @@
#include "perfetto/tracing.h"
#include "test/gtest_and_gmock.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h> // For CreateFile().
+#endif
+
// Deliberately not pulling any non-public perfetto header to spot accidental
// header public -> non-public dependency while building this file.
@@ -1508,7 +1512,7 @@
auto* tracing_session = NewTraceWithCategories({"foo"});
tracing_session->get()->StartBlocking();
- auto random_value = random();
+ auto random_value = rand();
TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
[random_value](perfetto::EventContext ctx) {
auto* log = ctx.event()->set_log_message();
@@ -1855,8 +1859,8 @@
auto* tracing_session = NewTraceWithCategories({"test"});
tracing_session->get()->StartBlocking();
- enum MyEnum { ENUM_FOO, ENUM_BAR };
- enum MySignedEnum { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
+ enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
+ enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
TRACE_EVENT_BEGIN("test", "E", "bool_arg", false);
TRACE_EVENT_BEGIN("test", "E", "int_arg", -123);
@@ -2416,7 +2420,7 @@
// This usleep is here just to prevent that we accidentally pass the test
// just by virtue of hitting some race. We should be able to trace up until
// 5 seconds after seeing the stop when using the deferred stop mechanism.
- usleep(250 * 1000);
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
MockDataSource::Trace([&lambda_called](MockDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
@@ -2473,30 +2477,29 @@
}
TEST_P(PerfettoApiTest, SetupWithFile) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
- char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
-#else
- char temp_file[] = "/tmp/perfetto-XXXXXXXX";
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ if (GetParam() == perfetto::kSystemBackend)
+ GTEST_SKIP() << "write_into_file + system mode is not supported on Windows";
#endif
- int fd = mkstemp(temp_file);
- ASSERT_TRUE(fd >= 0);
-
+ auto temp_file = perfetto::test::CreateTempFile();
perfetto::TraceConfig cfg;
cfg.set_duration_ms(500);
cfg.add_buffers()->set_size_kb(1024);
auto* ds_cfg = cfg.add_data_sources()->mutable_config();
ds_cfg->set_name("my_data_source");
// Write a trace into |fd|.
- auto* tracing_session = NewTrace(cfg, fd);
+ auto* tracing_session = NewTrace(cfg, temp_file.fd);
tracing_session->get()->StartBlocking();
tracing_session->get()->StopBlocking();
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Check that |fd| didn't get closed.
- EXPECT_EQ(0, fcntl(fd, F_GETFD, 0));
+ EXPECT_EQ(0, fcntl(temp_file.fd, F_GETFD, 0));
+#endif
// Check that the trace got written.
- EXPECT_GT(lseek(fd, 0, SEEK_END), 0);
- EXPECT_EQ(0, close(fd));
+ EXPECT_GT(lseek(temp_file.fd, 0, SEEK_END), 0);
+ EXPECT_EQ(0, close(temp_file.fd));
// Clean up.
- EXPECT_EQ(0, unlink(temp_file));
+ EXPECT_EQ(0, remove(temp_file.path.c_str()));
}
TEST_P(PerfettoApiTest, MultipleRegistrations) {
@@ -3185,15 +3188,8 @@
TEST_P(PerfettoApiTest, ConsoleInterceptorVerify) {
perfetto::ConsoleInterceptor::Register();
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
- char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
-#else
- char temp_file[] = "/tmp/perfetto-XXXXXXXX";
-#endif
- int fd = mkstemp(temp_file);
- ASSERT_TRUE(fd >= 0);
- perfetto::ConsoleInterceptor::SetOutputFdForTesting(fd);
+ auto temp_file = perfetto::test::CreateTempFile();
+ perfetto::ConsoleInterceptor::SetOutputFdForTesting(temp_file.fd);
perfetto::TraceConfig cfg;
cfg.set_duration_ms(500);
@@ -3209,7 +3205,7 @@
perfetto::ConsoleInterceptor::SetOutputFdForTesting(0);
std::vector<std::string> lines;
- FILE* f = fdopen(fd, "r");
+ FILE* f = fdopen(temp_file.fd, "r");
fseek(f, 0u, SEEK_SET);
std::array<char, 128> line{};
while (fgets(line.data(), line.size(), f)) {
@@ -3220,7 +3216,7 @@
lines.push_back(std::move(s));
}
fclose(f);
- EXPECT_EQ(0, unlink(temp_file));
+ EXPECT_EQ(0, remove(temp_file.path.c_str()));
// clang-format off
std::vector<std::string> golden_lines = {
diff --git a/src/tracing/test/api_test_support.cc b/src/tracing/test/api_test_support.cc
index f8f5aa8..4eaec20 100644
--- a/src/tracing/test/api_test_support.cc
+++ b/src/tracing/test/api_test_support.cc
@@ -102,5 +102,29 @@
return muxer->EnableDirectSMBPatchingForTesting(backend_type);
}
+TestTempFile CreateTempFile() {
+ TestTempFile res{};
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ char temp_file[255]{};
+ sprintf(temp_file, "%s\\perfetto-XXXXXX", getenv("TMP"));
+ PERFETTO_CHECK(_mktemp_s(temp_file, strlen(temp_file) + 1) == 0);
+ HANDLE handle =
+ ::CreateFileA(temp_file, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY, nullptr);
+ PERFETTO_CHECK(handle && handle != INVALID_HANDLE_VALUE);
+ res.fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle), 0);
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
+ res.fd = mkstemp(temp_file);
+#else
+ char temp_file[] = "/tmp/perfetto-XXXXXXXX";
+ res.fd = mkstemp(temp_file);
+#endif
+ res.path = temp_file;
+ PERFETTO_CHECK(res.fd > 0);
+ return res;
+}
+
} // namespace test
} // namespace perfetto
diff --git a/src/tracing/test/api_test_support.h b/src/tracing/test/api_test_support.h
index 55ae08f..33a7a53 100644
--- a/src/tracing/test/api_test_support.h
+++ b/src/tracing/test/api_test_support.h
@@ -43,6 +43,14 @@
void DisableReconnectLimit();
+struct TestTempFile {
+ int fd;
+ std::string path;
+};
+
+// The caller must close(2) the returned TempFile.fd.
+TestTempFile CreateTempFile();
+
} // namespace test
} // namespace perfetto
diff --git a/src/tracing/test/platform_unittest.cc b/src/tracing/test/platform_unittest.cc
new file mode 100644
index 0000000..8608664
--- /dev/null
+++ b/src/tracing/test/platform_unittest.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 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 "perfetto/tracing/platform.h"
+
+#include <atomic>
+
+#include "perfetto/base/task_runner.h"
+#include "perfetto/ext/base/waitable_event.h"
+#include "perfetto/tracing/internal/tracing_tls.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+internal::TracingTLS* GetTLS() {
+ return static_cast<internal::TracingTLS*>(
+ Platform::GetDefaultPlatform()->GetOrCreateThreadLocalObject());
+}
+
+// We use this class only as a listener to detect thread-local destruction.
+class FakeTraceWriter : public TraceWriterBase {
+ public:
+ std::atomic<bool>* destroyed_flag;
+
+ ~FakeTraceWriter() override { *destroyed_flag = true; }
+ protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket() {
+ PERFETTO_CHECK(false);
+ }
+ void Flush(std::function<void()>) override {}
+ uint64_t written() const override { return 0; }
+};
+
+// This test mainly checks that the thread at-exit logic works properly and
+// destroys the TracingTLS when a thread exits.
+TEST(PlatformUnittest, ThreadingAndTLSDtor) {
+ auto* platform = Platform::GetDefaultPlatform();
+ if (!platform)
+ GTEST_SKIP() << "Platform::GetDefaultPlatform() not implemented";
+
+ auto proc_name = platform->GetCurrentProcessName();
+ EXPECT_FALSE(proc_name.empty());
+
+ // Create two threads.
+
+ Platform::CreateTaskRunnerArgs tr_args{};
+ auto thread1 = platform->CreateTaskRunner(tr_args);
+ ASSERT_TRUE(thread1);
+
+ auto thread2 = platform->CreateTaskRunner(tr_args);
+ ASSERT_TRUE(thread2);
+
+ // Check that the TLS is actually thread-local.
+
+ thread1->PostTask([] { GetTLS()->generation = 101; });
+ thread2->PostTask([] { GetTLS()->generation = 102; });
+ std::atomic<bool> thread1_destroyed{};
+ std::atomic<bool> thread2_destroyed{};
+
+ // Now post another task on each thread. The task will:
+ // 1. Check that the generation matches what previously set.
+ // 2. Create a FakeTraceWriter and wire up a destruction event.
+ base::WaitableEvent evt1;
+ thread1->PostTask([&] {
+ EXPECT_EQ(GetTLS()->generation, 101u);
+ GetTLS()->data_sources_tls[0].per_instance[0].Reset();
+ std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
+ tw->destroyed_flag = &thread1_destroyed;
+ GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
+ evt1.Notify();
+ });
+ evt1.Wait();
+
+ base::WaitableEvent evt2;
+ thread2->PostTask([&] {
+ EXPECT_EQ(GetTLS()->generation, 102u);
+ GetTLS()->data_sources_tls[0].per_instance[0].Reset();
+ std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
+ tw->destroyed_flag = &thread2_destroyed;
+ GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
+ evt2.Notify();
+ });
+ evt2.Wait();
+
+ EXPECT_FALSE(thread1_destroyed);
+ EXPECT_FALSE(thread2_destroyed);
+
+ thread1.reset();
+ EXPECT_TRUE(thread1_destroyed);
+ EXPECT_FALSE(thread2_destroyed);
+
+ thread2.reset();
+ EXPECT_TRUE(thread2_destroyed);
+}
+
+} // namespace
+} // namespace perfetto
diff --git a/src/tracing/test/test_shared_memory.h b/src/tracing/test/test_shared_memory.h
index 2a323bf..9db6bcb 100644
--- a/src/tracing/test/test_shared_memory.h
+++ b/src/tracing/test/test_shared_memory.h
@@ -41,7 +41,6 @@
void* start() const override { return mem_.Get(); }
size_t size() const override { return size_; }
- int fd() const override { return -1; }
base::PagedMemory mem_;
size_t size_;
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 9ddfaa8..1fd624b 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -298,6 +298,8 @@
std::vector<TracePacket>* packets, bool has_more) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
const int kExpectedMinNumberOfClocks = 1;
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ const int kExpectedMinNumberOfClocks = 2;
#else
const int kExpectedMinNumberOfClocks = 6;
#endif
@@ -372,6 +374,7 @@
// connection and trigger the EXPECT_CALL(OnTracingDisabled) above.
}
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
TEST_F(TracingIntegrationTest, WriteIntoFile) {
// Start tracing.
TraceConfig trace_config;
@@ -452,6 +455,7 @@
ASSERT_GT(num_clock_snapshot_packet, 0u);
ASSERT_GT(num_system_info_packet, 0u);
}
+#endif
class TracingIntegrationTestWithSMBScrapingProducer
: public TracingIntegrationTest {
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 46ff80e..53c8369 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -147,7 +147,7 @@
cmd.insert(cmd.end(), args.begin(), args.end());
}
- if (access(cmd[0].c_str(), F_OK)) {
+ if (!base::FileExists(cmd[0])) {
PERFETTO_FATAL(
"Cannot find %s. Make sure that the target has been built and, on "
"Android, pushed to the device.",
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index d35a674..f716c90 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -17,6 +17,7 @@
#include "test/fake_producer.h"
#include <mutex>
+#include <thread>
#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
@@ -161,7 +162,7 @@
endpoint_->NotifyFlushComplete(flush_request_id);
}
-int FakeProducer::unix_socket_fd() {
+base::SocketHandle FakeProducer::unix_socket_fd() {
// Since FakeProducer is only used in tests we can include and assume the
// implementation.
auto* producer = static_cast<ProducerIPCClientImpl*>(endpoint_.get());
@@ -210,8 +211,8 @@
int64_t expected_time_taken = iterations * 1000;
base::TimeMillis time_taken = base::GetWallTimeMs() - start;
while (time_taken.count() < expected_time_taken) {
- usleep(static_cast<useconds_t>(
- (expected_time_taken - time_taken.count()) * 1000));
+ std::this_thread::sleep_for(
+ base::TimeMillis(expected_time_taken - time_taken.count()));
time_taken = base::GetWallTimeMs() - start;
}
}
diff --git a/test/fake_producer.h b/test/fake_producer.h
index c248051..27cd5d3 100644
--- a/test/fake_producer.h
+++ b/test/fake_producer.h
@@ -22,6 +22,7 @@
#include <string>
#include "perfetto/ext/base/thread_checker.h"
+#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/tracing/core/producer.h"
#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
@@ -82,7 +83,7 @@
size_t /*num_data_sources*/) override {}
// For testing, access to the fd used to communicate with the TracingService.
- int unix_socket_fd();
+ base::SocketHandle unix_socket_fd();
private:
void SetupFromConfig(const protos::gen::TestConfig& config);
diff --git a/test/stress_test/stress_test.cc b/test/stress_test/stress_test.cc
index 4fa0d2d..c8e9503 100644
--- a/test/stress_test/stress_test.cc
+++ b/test/stress_test/stress_test.cc
@@ -124,9 +124,9 @@
TestHarness::TestHarness() {
results_dir_ = base::GetSysTempDir() + "/perfetto-stress-test";
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
- system(("rmdir \"" + results_dir_ + "\" /s /q").c_str());
+ base::ignore_result(system(("rmdir \"" + results_dir_ + "\" /s /q").c_str()));
#else
- system(("rm -r -- \"" + results_dir_ + "\"").c_str());
+ base::ignore_result(system(("rm -r -- \"" + results_dir_ + "\"").c_str()));
#endif
PERFETTO_CHECK(base::Mkdir(results_dir_));
PERFETTO_LOG("Saving test results in %s", results_dir_.c_str());
diff --git a/test/test_helper.h b/test/test_helper.h
index d1cce2b..8985cf5 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -17,8 +17,13 @@
#ifndef TEST_TEST_HELPER_H_
#define TEST_TEST_HELPER_H_
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_task_runner.h"
+#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
@@ -26,9 +31,15 @@
#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
#include "perfetto/tracing/core/trace_config.h"
#include "src/base/test/test_task_runner.h"
+#include "test/fake_producer.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// TODO(primiano): uncomment in next CL.
+// #include "src/tracing/ipc/shared_memory_windows.h"
+#else
#include "src/traced/probes/probes_producer.h"
#include "src/tracing/ipc/posix_shared_memory.h"
-#include "test/fake_producer.h"
+#endif
#include "protos/perfetto/trace/trace_packet.gen.h"
@@ -56,12 +67,10 @@
runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.svc");
runner_->PostTaskAndWaitForTesting([this]() {
svc_ = ServiceIPCHost::CreateInstance(runner_->get());
- unlink(producer_socket_.c_str());
- unlink(consumer_socket_.c_str());
- setenv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket_.c_str(),
- /*overwrite=*/true);
- setenv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket_.c_str(),
- /*overwrite=*/true);
+ remove(producer_socket_.c_str());
+ remove(consumer_socket_.c_str());
+ base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket_);
+ base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket_);
bool res =
svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
PERFETTO_CHECK(res);
@@ -79,6 +88,15 @@
};
// This is used only in daemon starting integrations tests.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// On Windows we don't have any traced_probes, make this a no-op to avoid
+// propagating #ifdefs to the outer test.
+class ProbesProducerThread {
+ public:
+ ProbesProducerThread(const std::string& /*producer_socket*/) {}
+ void Connect() {}
+};
+#else
class ProbesProducerThread {
public:
ProbesProducerThread(const std::string& producer_socket)
@@ -104,6 +122,7 @@
std::string producer_socket_;
std::unique_ptr<ProbesProducer> producer_;
};
+#endif // !OS_WIN
class FakeProducerThread {
public:
@@ -139,9 +158,13 @@
FakeProducer* producer() { return producer_.get(); }
void CreateProducerProvidedSmb() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // TODO(primiano): in next CLs introduce SharedMemoryWindows.
+#else
PosixSharedMemory::Factory factory;
shm_ = factory.CreateSharedMemory(1024 * 1024);
shm_arbiter_ = SharedMemoryArbiter::CreateUnboundInstance(shm_.get(), 4096);
+#endif
}
void ProduceStartupEventBatch(const protos::gen::TestConfig& config,