ust: add global Makefile
[ust.git] / libtracectl / tracectl.c
CommitLineData
68c1021b
PMF
1#include <stdio.h>
2#include <stdint.h>
3#include <signal.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <sys/un.h>
98963de4 7#include <sched.h>
fbd8191b
PMF
8
9#include "marker.h"
10
68c1021b
PMF
11#define UNIX_PATH_MAX 108
12
13//#define SOCKETDIR "/var/run/ust/socks"
14#define SOCKETDIR "/tmp/socks"
15#define SOCKETDIRLEN sizeof(SOCKETDIR)
16#define USTSIGNAL SIGIO
17
18#define DBG(fmt, args...) fprintf(stderr, fmt "\n", ## args)
19#define WARN(fmt, args...) fprintf(stderr, "usertrace: WARNING: " fmt "\n", ## args)
20#define ERR(fmt, args...) fprintf(stderr, "usertrace: ERROR: " fmt "\n", ## args)
21#define PERROR(call) perror("usertrace: ERROR: " call)
22
98963de4
PMF
23#define MAX_MSG_SIZE (100)
24#define MSG_NOTIF 1
25#define MSG_REGISTER_NOTIF 2
26
68c1021b
PMF
27struct tracecmd { /* no padding */
28 uint32_t size;
29 uint16_t command;
30};
31
98963de4
PMF
32//struct listener_arg {
33// int pipe_fd;
34//};
35
36struct trctl_msg {
37 /* size: the size of all the fields except size itself */
38 uint32_t size;
39 uint16_t type;
40 /* Only the necessary part of the payload is transferred. It
41 * may even be none of it.
42 */
43 char payload[94];
44};
68c1021b
PMF
45
46pid_t mypid;
47char mysocketfile[UNIX_PATH_MAX] = "";
98963de4 48int pfd = -1;
68c1021b 49
fbd8191b
PMF
50
51static void print_markers(void)
52{
53 struct marker_iter iter;
54
55 marker_iter_reset(&iter);
56 marker_iter_start(&iter);
57
58 while(iter.marker) {
59 fprintf(stderr, "marker: %s_%s \"%s\"\n", iter.marker->channel, iter.marker->name, iter.marker->format);
60 marker_iter_next(&iter);
61 }
62}
63
68c1021b
PMF
64void do_command(struct tracecmd *cmd)
65{
66}
67
68void receive_commands()
69{
70}
71
98963de4
PMF
72int fd_notif = -1;
73void notif_cb(void)
74{
75 int result;
76 struct trctl_msg msg;
77
78 /* FIXME: fd_notif should probably be protected by a spinlock */
79
80 if(fd_notif == -1)
81 return;
82
83 msg.type = MSG_NOTIF;
84 msg.size = sizeof(msg.type);
85
86 /* FIXME: don't block here */
87 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
88 if(result == -1) {
89 PERROR("write");
90 return;
91 }
92}
93
fbd8191b
PMF
94char recvbuf[10000];
95
98963de4
PMF
96int listener_main(void *p)
97{
98 int result;
99
98963de4 100 for(;;) {
98963de4 101 uint32_t size;
98963de4
PMF
102 struct sockaddr_un addr;
103 socklen_t addrlen = sizeof(addr);
aafb1650
PMF
104 char trace_name[] = "auto";
105 char trace_type[] = "ustrelay";
98963de4 106
98963de4
PMF
107 for(;;) {
108 struct trctl_msg msg;
fbd8191b 109 int len;
98963de4 110
fbd8191b 111 result = len = recvfrom(pfd, recvbuf, sizeof(recvbuf), 0, &addr, &addrlen);
98963de4 112 if(result == -1) {
fbd8191b 113 PERROR("recvfrom");
98963de4
PMF
114 continue;
115 }
116
aafb1650
PMF
117 if(recvbuf[len-1] == '\n')
118 recvbuf[len-1] = '\0';
98963de4 119
fbd8191b 120 fprintf(stderr, "received a message! it's: %s\n", recvbuf);
98963de4 121
fbd8191b
PMF
122
123 if(!strcmp(recvbuf, "print_markers")) {
124 print_markers();
125 }
126 else if(!strcmp(recvbuf, "trace_setup")) {
127 DBG("trace setup");
aafb1650
PMF
128
129 result = ltt_trace_setup(trace_name);
130 if(result < 0) {
131 ERR("ltt_trace_setup failed");
132 return;
133 }
134
135 result = ltt_trace_set_type(trace_name, trace_type);
136 if(result < 0) {
137 ERR("ltt_trace_set_type failed");
138 return;
139 }
fbd8191b
PMF
140 }
141 else if(!strcmp(recvbuf, "trace_alloc")) {
142 DBG("trace alloc");
aafb1650
PMF
143
144 result = ltt_trace_alloc(trace_name);
145 if(result < 0) {
146 ERR("ltt_trace_alloc failed");
147 return;
148 }
fbd8191b
PMF
149 }
150 else if(!strcmp(recvbuf, "trace_start")) {
151 DBG("trace start");
aafb1650
PMF
152
153 result = ltt_trace_start(trace_name);
154 if(result < 0) {
155 ERR("ltt_trace_start failed");
156 return;
157 }
fbd8191b
PMF
158 }
159 else if(!strcmp(recvbuf, "trace_stop")) {
160 DBG("trace stop");
aafb1650
PMF
161
162 result = ltt_trace_stop(trace_name);
163 if(result < 0) {
164 ERR("ltt_trace_stop failed");
165 return;
166 }
167 }
168 else if(!strcmp(recvbuf, "trace_destroy")) {
169
170 DBG("trace destroy");
171
172 result = ltt_trace_destroy(trace_name);
173 if(result < 0) {
174 ERR("ltt_trace_destroy failed");
175 return;
176 }
fbd8191b 177 }
98963de4
PMF
178 }
179 next_conn:;
180 }
181}
182
183void create_listener(void)
184{
185 int result;
186 static char listener_stack[16384];
187
fbd8191b 188 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
189 if(result == -1) {
190 perror("clone");
191 }
192}
193
68c1021b
PMF
194/* The signal handler itself. */
195
196void sighandler(int sig)
197{
198 DBG("sighandler");
fbd8191b 199 create_listener();
68c1021b
PMF
200}
201
202/* Called by the app signal handler to chain it to us. */
203
98963de4 204void chain_signal(void)
68c1021b
PMF
205{
206 sighandler(USTSIGNAL);
207}
208
98963de4 209static int init_socket(void)
68c1021b
PMF
210{
211 int result;
212 int fd;
213 char pidstr[6];
214 int pidlen;
215
216 struct sockaddr_un addr;
217
fbd8191b 218 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
68c1021b
PMF
219 if(result == -1) {
220 PERROR("socket");
221 return -1;
222 }
223
224 addr.sun_family = AF_UNIX;
225
226 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d", SOCKETDIR, mypid);
227 if(result >= UNIX_PATH_MAX) {
228 ERR("string overflow allocating socket name");
229 goto close_sock;
230 }
231 //DBG("opening socket at %s", addr.sun_path);
232
233 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
234 if(result == -1) {
235 PERROR("bind");
236 goto close_sock;
237 }
238
239 strcpy(mysocketfile, addr.sun_path);
240
98963de4
PMF
241 pfd = fd;
242 return 0;
243
68c1021b
PMF
244 close_sock:
245 close(fd);
246
247 return -1;
248}
249
98963de4 250static void destroy_socket(void)
68c1021b
PMF
251{
252 int result;
253
254 if(mysocketfile[0] == '\0')
255 return;
256
257 result = unlink(mysocketfile);
258 if(result == -1) {
259 PERROR("unlink");
260 }
261}
262
98963de4 263static int init_signal_handler(void)
68c1021b
PMF
264{
265 /* Attempt to handler SIGIO. If the main program wants to
266 * handle it, fine, it'll override us. They it'll have to
267 * use the chaining function.
268 */
269
270 int result;
271 struct sigaction act;
272
273 result = sigemptyset(&act.sa_mask);
274 if(result == -1) {
275 PERROR("sigemptyset");
276 return -1;
277 }
278
279 act.sa_handler = sighandler;
280 act.sa_flags = SA_RESTART;
281
282 /* Only defer ourselves. Also, try to restart interrupted
283 * syscalls to disturb the traced program as little as possible.
284 */
285 result = sigaction(SIGIO, &act, NULL);
286 if(result == -1) {
287 PERROR("sigaction");
288 return -1;
289 }
290
291 return 0;
292}
293
98963de4 294static void __attribute__((constructor)) init()
68c1021b
PMF
295{
296 int result;
297
298 mypid = getpid();
299
4db647c5
PMF
300 if(getenv("UST_TRACE")) {
301 char trace_name[] = "auto";
302 char trace_type[] = "ustrelay";
303
304 DBG("starting early tracing");
305
306 /* Ensure marker control is initialized */
307 init_marker_control();
308
309 /* Ensure relay is initialized */
310 init_ustrelay_transport();
311
312 /* Ensure markers are initialized */
313 init_markers();
314
315 result = ltt_marker_connect("foo", "bar", "default");
316 if(result)
317 ERR("ltt_marker_connect");
aafb1650
PMF
318
319 result = ltt_marker_connect("foo", "bar2", "default");
320 if(result)
321 ERR("ltt_marker_connect");
4db647c5
PMF
322
323 result = ltt_trace_setup(trace_name);
324 if(result < 0) {
325 ERR("ltt_trace_setup failed");
326 return;
327 }
328
329 result = ltt_trace_set_type(trace_name, trace_type);
330 if(result < 0) {
331 ERR("ltt_trace_set_type failed");
332 return;
333 }
334
335 result = ltt_trace_alloc(trace_name);
336 if(result < 0) {
337 ERR("ltt_trace_alloc failed");
338 return;
339 }
340
341 result = ltt_trace_start(trace_name);
342 if(result < 0) {
343 ERR("ltt_trace_start failed");
344 return;
345 }
346 }
347
98963de4
PMF
348 /* Must create socket before signal handler to prevent races
349 * on pfd variable.
350 */
68c1021b 351 result = init_socket();
98963de4
PMF
352 if(result == -1) {
353 ERR("init_socket error");
354 return;
355 }
356 result = init_signal_handler();
357 if(result == -1) {
358 ERR("init_signal_handler error");
359 return;
360 }
68c1021b
PMF
361
362 return;
363
364 /* should decrementally destroy stuff if error */
365
366}
367
368/* This is only called if we terminate normally, not with an unhandled signal,
369 * so we cannot rely on it. */
370
98963de4 371static void __attribute__((destructor)) fini()
68c1021b
PMF
372{
373 destroy_socket();
374}
This page took 0.036912 seconds and 4 git commands to generate.