Fix: futex wait: handle spurious futex wakeups
[lttng-tools.git] / src / common / fd-tracker / utils.cpp
1 /*
2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/error.hpp>
9 #include <common/fd-tracker/utils.hpp>
10 #include <common/utils.hpp>
11 #include <lttng/constant.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15
16 static
17 int open_pipe_cloexec(void *data __attribute__((unused)), int *fds)
18 {
19 return utils_create_pipe_cloexec(fds);
20 }
21
22 static
23 int close_pipe(void *data __attribute__((unused)), int *pipe)
24 {
25 utils_close_pipe(pipe);
26 pipe[0] = pipe[1] = -1;
27 return 0;
28 }
29
30 int fd_tracker_util_close_fd(void *unused __attribute__((unused)), int *fd)
31 {
32 return close(*fd);
33 }
34
35 int fd_tracker_util_pipe_open_cloexec(
36 struct fd_tracker *tracker, const char *name, int *pipe)
37 {
38 int ret;
39 const char *name_prefix;
40 char *names[2];
41
42 name_prefix = name ? name : "Unknown pipe";
43 ret = asprintf(&names[0], "%s (read end)", name_prefix);
44 if (ret < 0) {
45 goto end;
46 }
47 ret = asprintf(&names[1], "%s (write end)", name_prefix);
48 if (ret < 0) {
49 goto end;
50 }
51
52 ret = fd_tracker_open_unsuspendable_fd(tracker, pipe,
53 (const char **) names, 2, open_pipe_cloexec, NULL);
54 free(names[0]);
55 free(names[1]);
56 end:
57 return ret;
58 }
59
60 int fd_tracker_util_pipe_close(struct fd_tracker *tracker, int *pipe)
61 {
62 return fd_tracker_close_unsuspendable_fd(
63 tracker, pipe, 2, close_pipe, NULL);
64 }
65
66 namespace {
67 struct open_directory_handle_args {
68 const struct lttng_directory_handle *in_handle;
69 struct lttng_directory_handle *ret_handle;
70 const char *path;
71 };
72 } /* namespace */
73
74 static
75 int open_directory_handle(void *_args, int *out_fds)
76 {
77 int ret = 0;
78 struct open_directory_handle_args *args = (open_directory_handle_args *) _args;
79 struct lttng_directory_handle *new_handle = NULL;
80
81 new_handle = args->in_handle ?
82 lttng_directory_handle_create_from_handle(
83 args->path, args->in_handle) :
84 lttng_directory_handle_create(args->path);
85 if (!new_handle) {
86 ret = -errno;
87 goto end;
88 }
89
90 args->ret_handle = new_handle;
91
92 /*
93 * Reserved to indicate that the handle does not use a handle; there is
94 * nothing to track. We want to indicate an error to the fd-tracker so
95 * that it doesn't attempt to track the file descriptor, but also want
96 * the caller to retrieve the newly-created handle.
97 *
98 * Calling this a hack is a fair assessment.
99 */
100 if (!lttng_directory_handle_uses_fd(new_handle)) {
101 ret = ENOTSUP;
102 } else {
103 #ifdef HAVE_DIRFD
104 *out_fds = new_handle->dirfd;
105 #else
106 abort();
107 #endif
108
109 }
110 end:
111 return ret;
112 }
113
114 #ifdef HAVE_DIRFD
115 static
116 int fd_close(void *unused __attribute__((unused)), int *in_fds)
117 {
118 const int ret = close(in_fds[0]);
119
120 in_fds[0] = -1;
121 return ret;
122 }
123
124 static
125 void directory_handle_destroy(
126 struct lttng_directory_handle *handle, void *data)
127 {
128 struct fd_tracker *tracker = (fd_tracker *) data;
129 const int ret = fd_tracker_close_unsuspendable_fd(
130 tracker, &handle->dirfd, 1, fd_close, NULL);
131
132 if (ret) {
133 ERR("Failed to untrack directory handle file descriptor");
134 }
135 }
136 #endif
137
138 struct lttng_directory_handle *fd_tracker_create_directory_handle(
139 struct fd_tracker *tracker, const char *path)
140 {
141 return fd_tracker_create_directory_handle_from_handle(
142 tracker, NULL, path);
143 }
144
145 struct lttng_directory_handle *fd_tracker_create_directory_handle_from_handle(
146 struct fd_tracker *tracker,
147 struct lttng_directory_handle *in_handle,
148 const char *path)
149 {
150 int ret;
151 int dirfd = -1;
152 char *handle_name = NULL;
153 char cwd_path[LTTNG_PATH_MAX] = "working directory";
154 struct lttng_directory_handle *new_handle = NULL;
155 open_directory_handle_args open_args {};
156
157 open_args.in_handle = in_handle;
158 open_args.path = path;
159
160 if (!path) {
161 if (!getcwd(cwd_path, sizeof(cwd_path))) {
162 PERROR("Failed to get current working directory to name directory handle");
163 goto end;
164 }
165 }
166
167 ret = asprintf(&handle_name, "Directory handle to %s",
168 path ? path : cwd_path);
169 if (ret < 0) {
170 PERROR("Failed to format directory handle name");
171 goto end;
172 }
173
174 ret = fd_tracker_open_unsuspendable_fd(tracker, &dirfd,
175 (const char **) &handle_name, 1, open_directory_handle,
176 &open_args);
177 if (ret && ret != ENOTSUP) {
178 ERR("Failed to open directory handle to %s through the fd tracker", path ? path : cwd_path);
179 }
180 new_handle = open_args.ret_handle;
181
182 #ifdef HAVE_DIRFD
183 new_handle->destroy_cb = directory_handle_destroy;
184 new_handle->destroy_cb_data = tracker;
185 #endif
186 end:
187 free(handle_name);
188 return new_handle;
189 }
This page took 0.032664 seconds and 4 git commands to generate.