ust: collect many channels and start work on pipe listener
[lttng-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>
68c1021b
PMF
8#define UNIX_PATH_MAX 108
9
10//#define SOCKETDIR "/var/run/ust/socks"
11#define SOCKETDIR "/tmp/socks"
12#define SOCKETDIRLEN sizeof(SOCKETDIR)
13#define USTSIGNAL SIGIO
14
15#define DBG(fmt, args...) fprintf(stderr, fmt "\n", ## args)
16#define WARN(fmt, args...) fprintf(stderr, "usertrace: WARNING: " fmt "\n", ## args)
17#define ERR(fmt, args...) fprintf(stderr, "usertrace: ERROR: " fmt "\n", ## args)
18#define PERROR(call) perror("usertrace: ERROR: " call)
19
98963de4
PMF
20#define MAX_MSG_SIZE (100)
21#define MSG_NOTIF 1
22#define MSG_REGISTER_NOTIF 2
23
68c1021b
PMF
24struct tracecmd { /* no padding */
25 uint32_t size;
26 uint16_t command;
27};
28
98963de4
PMF
29//struct listener_arg {
30// int pipe_fd;
31//};
32
33struct trctl_msg {
34 /* size: the size of all the fields except size itself */
35 uint32_t size;
36 uint16_t type;
37 /* Only the necessary part of the payload is transferred. It
38 * may even be none of it.
39 */
40 char payload[94];
41};
68c1021b
PMF
42
43pid_t mypid;
44char mysocketfile[UNIX_PATH_MAX] = "";
98963de4 45int pfd = -1;
68c1021b
PMF
46
47void do_command(struct tracecmd *cmd)
48{
49}
50
51void receive_commands()
52{
53}
54
98963de4
PMF
55int fd_notif = -1;
56void notif_cb(void)
57{
58 int result;
59 struct trctl_msg msg;
60
61 /* FIXME: fd_notif should probably be protected by a spinlock */
62
63 if(fd_notif == -1)
64 return;
65
66 msg.type = MSG_NOTIF;
67 msg.size = sizeof(msg.type);
68
69 /* FIXME: don't block here */
70 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
71 if(result == -1) {
72 PERROR("write");
73 return;
74 }
75}
76
77int listener_main(void *p)
78{
79 int result;
80
81 /* Allowing only 1 connection for now. */
82 result = listen(pfd, 1);
83 if(result == -1) {
84 PERROR("listen");
85 return 1;
86 }
87
88 for(;;) {
89
90 uint32_t size;
91 int fd;
92 struct sockaddr_un addr;
93 socklen_t addrlen = sizeof(addr);
94
95 result = fd = accept(pfd, (struct sockaddr *)&addr, &addrlen);
96 if(result == -1) {
97 PERROR("accept");
98 continue;
99 }
100
101 for(;;) {
102 struct trctl_msg msg;
103 unsigned char dontclose=0;
104
105 result = read(fd, &msg.size, sizeof(msg.size));
106 if(result == -1) {
107 PERROR("read");
108 continue;
109 }
110
111 if(size > MAX_MSG_SIZE) {
112 ERR("trctl message too big");
113 break;
114 }
115
116 result = read(fd, &msg.type, sizeof(msg.type));
117 if(result == -1) {
118 PERROR("read");
119 continue;
120 }
121
122 switch(msg.type) {
123 case MSG_REGISTER_NOTIF:
124 /* TODO: put it in notif mode */
125 goto next_conn;
126 };
127 }
128 next_conn:;
129 }
130}
131
132void create_listener(void)
133{
134 int result;
135 static char listener_stack[16384];
136
137 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM, NULL);
138 if(result == -1) {
139 perror("clone");
140 }
141}
142
68c1021b
PMF
143/* The signal handler itself. */
144
145void sighandler(int sig)
146{
147 DBG("sighandler");
148 receive_commands();
149}
150
151/* Called by the app signal handler to chain it to us. */
152
98963de4 153void chain_signal(void)
68c1021b
PMF
154{
155 sighandler(USTSIGNAL);
156}
157
98963de4 158static int init_socket(void)
68c1021b
PMF
159{
160 int result;
161 int fd;
162 char pidstr[6];
163 int pidlen;
164
165 struct sockaddr_un addr;
166
167 result = fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
168 if(result == -1) {
169 PERROR("socket");
170 return -1;
171 }
172
173 addr.sun_family = AF_UNIX;
174
175 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d", SOCKETDIR, mypid);
176 if(result >= UNIX_PATH_MAX) {
177 ERR("string overflow allocating socket name");
178 goto close_sock;
179 }
180 //DBG("opening socket at %s", addr.sun_path);
181
182 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
183 if(result == -1) {
184 PERROR("bind");
185 goto close_sock;
186 }
187
188 strcpy(mysocketfile, addr.sun_path);
189
98963de4
PMF
190 pfd = fd;
191 return 0;
192
68c1021b
PMF
193 close_sock:
194 close(fd);
195
196 return -1;
197}
198
98963de4 199static void destroy_socket(void)
68c1021b
PMF
200{
201 int result;
202
203 if(mysocketfile[0] == '\0')
204 return;
205
206 result = unlink(mysocketfile);
207 if(result == -1) {
208 PERROR("unlink");
209 }
210}
211
98963de4 212static int init_signal_handler(void)
68c1021b
PMF
213{
214 /* Attempt to handler SIGIO. If the main program wants to
215 * handle it, fine, it'll override us. They it'll have to
216 * use the chaining function.
217 */
218
219 int result;
220 struct sigaction act;
221
222 result = sigemptyset(&act.sa_mask);
223 if(result == -1) {
224 PERROR("sigemptyset");
225 return -1;
226 }
227
228 act.sa_handler = sighandler;
229 act.sa_flags = SA_RESTART;
230
231 /* Only defer ourselves. Also, try to restart interrupted
232 * syscalls to disturb the traced program as little as possible.
233 */
234 result = sigaction(SIGIO, &act, NULL);
235 if(result == -1) {
236 PERROR("sigaction");
237 return -1;
238 }
239
240 return 0;
241}
242
98963de4 243static void __attribute__((constructor)) init()
68c1021b
PMF
244{
245 int result;
246
247 mypid = getpid();
248
98963de4
PMF
249 /* Must create socket before signal handler to prevent races
250 * on pfd variable.
251 */
68c1021b 252 result = init_socket();
98963de4
PMF
253 if(result == -1) {
254 ERR("init_socket error");
255 return;
256 }
257 result = init_signal_handler();
258 if(result == -1) {
259 ERR("init_signal_handler error");
260 return;
261 }
68c1021b
PMF
262
263 return;
264
265 /* should decrementally destroy stuff if error */
266
267}
268
269/* This is only called if we terminate normally, not with an unhandled signal,
270 * so we cannot rely on it. */
271
98963de4 272static void __attribute__((destructor)) fini()
68c1021b
PMF
273{
274 destroy_socket();
275}
This page took 0.034696 seconds and 5 git commands to generate.