ust: cleanup hello.c
[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);
104
98963de4
PMF
105 for(;;) {
106 struct trctl_msg msg;
fbd8191b 107 int len;
98963de4 108
fbd8191b 109 result = len = recvfrom(pfd, recvbuf, sizeof(recvbuf), 0, &addr, &addrlen);
98963de4 110 if(result == -1) {
fbd8191b 111 PERROR("recvfrom");
98963de4
PMF
112 continue;
113 }
114
fbd8191b
PMF
115 if(recvbuf[len-2] == '\n')
116 recvbuf[len-2] = '\0';
98963de4 117
fbd8191b 118 fprintf(stderr, "received a message! it's: %s\n", recvbuf);
98963de4 119
fbd8191b
PMF
120
121 if(!strcmp(recvbuf, "print_markers")) {
122 print_markers();
123 }
124 else if(!strcmp(recvbuf, "trace_setup")) {
125 DBG("trace setup");
126 }
127 else if(!strcmp(recvbuf, "trace_alloc")) {
128 DBG("trace alloc");
129 }
130 else if(!strcmp(recvbuf, "trace_start")) {
131 DBG("trace start");
132 }
133 else if(!strcmp(recvbuf, "trace_stop")) {
134 DBG("trace stop");
135 }
98963de4
PMF
136 }
137 next_conn:;
138 }
139}
140
141void create_listener(void)
142{
143 int result;
144 static char listener_stack[16384];
145
fbd8191b 146 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
147 if(result == -1) {
148 perror("clone");
149 }
150}
151
68c1021b
PMF
152/* The signal handler itself. */
153
154void sighandler(int sig)
155{
156 DBG("sighandler");
fbd8191b 157 create_listener();
68c1021b
PMF
158}
159
160/* Called by the app signal handler to chain it to us. */
161
98963de4 162void chain_signal(void)
68c1021b
PMF
163{
164 sighandler(USTSIGNAL);
165}
166
98963de4 167static int init_socket(void)
68c1021b
PMF
168{
169 int result;
170 int fd;
171 char pidstr[6];
172 int pidlen;
173
174 struct sockaddr_un addr;
175
fbd8191b 176 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
68c1021b
PMF
177 if(result == -1) {
178 PERROR("socket");
179 return -1;
180 }
181
182 addr.sun_family = AF_UNIX;
183
184 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d", SOCKETDIR, mypid);
185 if(result >= UNIX_PATH_MAX) {
186 ERR("string overflow allocating socket name");
187 goto close_sock;
188 }
189 //DBG("opening socket at %s", addr.sun_path);
190
191 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
192 if(result == -1) {
193 PERROR("bind");
194 goto close_sock;
195 }
196
197 strcpy(mysocketfile, addr.sun_path);
198
98963de4
PMF
199 pfd = fd;
200 return 0;
201
68c1021b
PMF
202 close_sock:
203 close(fd);
204
205 return -1;
206}
207
98963de4 208static void destroy_socket(void)
68c1021b
PMF
209{
210 int result;
211
212 if(mysocketfile[0] == '\0')
213 return;
214
215 result = unlink(mysocketfile);
216 if(result == -1) {
217 PERROR("unlink");
218 }
219}
220
98963de4 221static int init_signal_handler(void)
68c1021b
PMF
222{
223 /* Attempt to handler SIGIO. If the main program wants to
224 * handle it, fine, it'll override us. They it'll have to
225 * use the chaining function.
226 */
227
228 int result;
229 struct sigaction act;
230
231 result = sigemptyset(&act.sa_mask);
232 if(result == -1) {
233 PERROR("sigemptyset");
234 return -1;
235 }
236
237 act.sa_handler = sighandler;
238 act.sa_flags = SA_RESTART;
239
240 /* Only defer ourselves. Also, try to restart interrupted
241 * syscalls to disturb the traced program as little as possible.
242 */
243 result = sigaction(SIGIO, &act, NULL);
244 if(result == -1) {
245 PERROR("sigaction");
246 return -1;
247 }
248
249 return 0;
250}
251
98963de4 252static void __attribute__((constructor)) init()
68c1021b
PMF
253{
254 int result;
255
256 mypid = getpid();
257
98963de4
PMF
258 /* Must create socket before signal handler to prevent races
259 * on pfd variable.
260 */
68c1021b 261 result = init_socket();
98963de4
PMF
262 if(result == -1) {
263 ERR("init_socket error");
264 return;
265 }
266 result = init_signal_handler();
267 if(result == -1) {
268 ERR("init_signal_handler error");
269 return;
270 }
68c1021b
PMF
271
272 return;
273
274 /* should decrementally destroy stuff if error */
275
276}
277
278/* This is only called if we terminate normally, not with an unhandled signal,
279 * so we cannot rely on it. */
280
98963de4 281static void __attribute__((destructor)) fini()
68c1021b
PMF
282{
283 destroy_socket();
284}
This page took 0.032597 seconds and 4 git commands to generate.