Add benchmark directory to git ignore
[lttng-tools.git] / ltt-sessiond / traceable-app.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; only version 2
7 * of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #define _GNU_SOURCE
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <lttngerr.h>
28
29 #include "traceable-app.h"
30
31 /* Init ust traceabl application's list */
32 static struct ltt_traceable_app_list ltt_traceable_app_list = {
33 .head = CDS_LIST_HEAD_INIT(ltt_traceable_app_list.head),
34 .lock = PTHREAD_MUTEX_INITIALIZER,
35 .count = 0,
36 };
37
38 /*
39 * Add a traceable application structure to the global list.
40 */
41 static void add_traceable_app(struct ltt_traceable_app *lta)
42 {
43 cds_list_add(&lta->list, &ltt_traceable_app_list.head);
44 ltt_traceable_app_list.count++;
45 }
46
47 /*
48 * Delete a traceable application structure from the global list.
49 */
50 static void del_traceable_app(struct ltt_traceable_app *lta)
51 {
52 cds_list_del(&lta->list);
53 /* Sanity check */
54 if (ltt_traceable_app_list.count > 0) {
55 ltt_traceable_app_list.count--;
56 }
57 }
58
59 /*
60 * Return pointer to traceable apps list.
61 */
62 struct ltt_traceable_app_list *get_traceable_apps_list(void)
63 {
64 return &ltt_traceable_app_list;
65 }
66
67 /*
68 * Acquire traceable apps list lock.
69 */
70 void lock_apps_list(void)
71 {
72 pthread_mutex_lock(&ltt_traceable_app_list.lock);
73 }
74
75 /*
76 * Release traceable apps list lock.
77 */
78 void unlock_apps_list(void)
79 {
80 pthread_mutex_unlock(&ltt_traceable_app_list.lock);
81 }
82
83 /*
84 * Iterate over the traceable apps list and return a pointer or NULL if not
85 * found.
86 */
87 static struct ltt_traceable_app *find_app_by_sock(int sock)
88 {
89 struct ltt_traceable_app *iter;
90
91 cds_list_for_each_entry(iter, &ltt_traceable_app_list.head, list) {
92 if (iter->sock == sock) {
93 /* Found */
94 return iter;
95 }
96 }
97
98 return NULL;
99 }
100
101 /*
102 * Iterate over the traceable apps list and return a pointer or NULL if not
103 * found.
104 */
105 struct ltt_traceable_app *traceable_app_get_by_pid(pid_t pid)
106 {
107 struct ltt_traceable_app *iter;
108
109 cds_list_for_each_entry(iter, &ltt_traceable_app_list.head, list) {
110 if (iter->pid == pid) {
111 /* Found */
112 return iter;
113 }
114 }
115
116 return NULL;
117 }
118
119 /*
120 * Using pid and uid (of the app), allocate a new ltt_traceable_app struct and
121 * add it to the global traceable app list.
122 *
123 * On success, return 0, else return malloc ENOMEM.
124 */
125 int register_traceable_app(struct ust_register_msg *msg, int sock)
126 {
127 struct ltt_traceable_app *lta;
128
129 lta = malloc(sizeof(struct ltt_traceable_app));
130 if (lta == NULL) {
131 perror("malloc");
132 return -ENOMEM;
133 }
134
135 lta->uid = msg->uid;
136 lta->gid = msg->gid;
137 lta->pid = msg->pid;
138 lta->ppid = msg->ppid;
139 lta->v_major = msg->major;
140 lta->v_minor = msg->minor;
141 lta->sock = sock;
142 strncpy(lta->name, msg->name, sizeof(lta->name));
143 lta->name[16] = '\0';
144
145 lock_apps_list();
146 add_traceable_app(lta);
147 unlock_apps_list();
148
149 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
150 " (version %d.%d)", lta->pid, lta->ppid, lta->uid, lta->gid,
151 lta->sock, lta->name, lta->v_major, lta->v_minor);
152
153 return 0;
154 }
155
156 /*
157 * Unregister app by removing it from the global traceable app list and freeing
158 * the data struct.
159 *
160 * The socket is already closed at this point so no close to sock.
161 */
162 void unregister_traceable_app(int sock)
163 {
164 struct ltt_traceable_app *lta;
165
166 lock_apps_list();
167 lta = find_app_by_sock(sock);
168 if (lta) {
169 DBG("PID %d unregistered with sock %d", lta->pid, sock);
170 close(lta->sock);
171 del_traceable_app(lta);
172 unlock_apps_list();
173 free(lta);
174 }
175 unlock_apps_list();
176 }
177
178 /*
179 * Return traceable_app_count
180 */
181 unsigned int get_app_count(void)
182 {
183 unsigned int count;
184
185 lock_apps_list();
186 count = ltt_traceable_app_list.count;
187 unlock_apps_list();
188
189 return count;
190 }
191
192 /*
193 * Free and clean all traceable apps of the global list.
194 */
195 void clean_traceable_apps_list(void)
196 {
197 struct ltt_traceable_app *iter, *tmp;
198
199 /*
200 * Don't acquire list lock here. This function should be called from
201 * cleanup() functions meaning that the program will exit.
202 */
203 cds_list_for_each_entry_safe(iter, tmp, &ltt_traceable_app_list.head, list) {
204 close(iter->sock);
205 free(iter);
206 }
207 }
This page took 0.03251 seconds and 4 git commands to generate.