Add support for UST application registration
[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 * Using pid and uid (of the app), allocate a new ltt_traceable_app struct and
103 * add it to the global traceable app list.
104 *
105 * On success, return 0, else return malloc ENOMEM.
106 */
107 int register_traceable_app(struct ust_register_msg *msg, int sock)
108 {
109 struct ltt_traceable_app *lta;
110
111 lta = malloc(sizeof(struct ltt_traceable_app));
112 if (lta == NULL) {
113 perror("malloc");
114 return -ENOMEM;
115 }
116
117 lta->uid = msg->uid;
118 lta->gid = msg->gid;
119 lta->pid = msg->pid;
120 lta->ppid = msg->ppid;
121 lta->v_major = msg->major;
122 lta->v_minor = msg->minor;
123 lta->sock = sock;
124 strncpy(lta->name, msg->name, sizeof(lta->name));
125 lta->name[16] = '\0';
126
127 lock_apps_list();
128 add_traceable_app(lta);
129 unlock_apps_list();
130
131 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
132 " (version %d.%d)", lta->pid, lta->ppid, lta->uid, lta->gid,
133 lta->sock, lta->name, lta->v_major, lta->v_minor);
134
135 return 0;
136 }
137
138 /*
139 * Unregister app by removing it from the global traceable app list and freeing
140 * the data struct.
141 *
142 * The socket is already closed at this point so no close to sock.
143 */
144 void unregister_traceable_app(int sock)
145 {
146 struct ltt_traceable_app *lta;
147
148 lock_apps_list();
149 lta = find_app_by_sock(sock);
150 if (lta) {
151 DBG("PID %d unregistered with sock %d", lta->pid, sock);
152 close(lta->sock);
153 del_traceable_app(lta);
154 unlock_apps_list();
155 free(lta);
156 }
157 unlock_apps_list();
158 }
159
160 /*
161 * Return traceable_app_count
162 */
163 unsigned int get_app_count(void)
164 {
165 unsigned int count;
166
167 lock_apps_list();
168 count = ltt_traceable_app_list.count;
169 unlock_apps_list();
170
171 return count;
172 }
173
174 /*
175 * Free and clean all traceable apps of the global list.
176 */
177 void clean_traceable_apps_list(void)
178 {
179 struct ltt_traceable_app *iter, *tmp;
180
181 /*
182 * Don't acquire list lock here. This function should be called from
183 * cleanup() functions meaning that the program will exit.
184 */
185 cds_list_for_each_entry_safe(iter, tmp, &ltt_traceable_app_list.head, list) {
186 close(iter->sock);
187 free(iter);
188 }
189 }
This page took 0.045655 seconds and 4 git commands to generate.