nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2005 Matthias Clasen
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <signal.h>
21  
22 #include "glib.h"
23 #include "gstdio.h"
24  
25 #ifdef G_OS_UNIX
26 #include <unistd.h>
27 #endif
28  
29 static gchar *dir, *filename, *displayname, *childname;
30  
31 static gboolean stop = FALSE;
32  
33 static gint parent_pid;
34  
35 #ifndef G_OS_WIN32
36  
37 static void
38 handle_usr1 (int signum)
39 {
40 stop = TRUE;
41 }
42  
43 #endif
44  
45 static gboolean
46 check_stop (gpointer data)
47 {
48 GMainLoop *loop = data;
49  
50 #ifdef G_OS_WIN32
51 stop = g_file_test ("STOP", G_FILE_TEST_EXISTS);
52 #endif
53  
54 if (stop)
55 g_main_loop_quit (loop);
56  
57 return TRUE;
58 }
59  
60 static void
61 write_or_die (const gchar *filename,
62 const gchar *contents,
63 gssize length)
64 {
65 GError *error = NULL;
66 gchar *displayname;
67  
68 if (!g_file_set_contents (filename, contents, length, &error))
69 {
70 displayname = g_filename_display_name (childname);
71 g_print ("failed to write '%s': %s\n",
72 displayname, error->message);
73 exit (1);
74 }
75 }
76  
77 static GMappedFile *
78 map_or_die (const gchar *filename,
79 gboolean writable)
80 {
81 GError *error = NULL;
82 GMappedFile *map;
83 gchar *displayname;
84  
85 map = g_mapped_file_new (filename, writable, &error);
86 if (!map)
87 {
88 displayname = g_filename_display_name (childname);
89 g_print ("failed to map '%s' non-writable, shared: %s\n",
90 displayname, error->message);
91 exit (1);
92 }
93  
94 return map;
95 }
96  
97 static gboolean
98 signal_parent (gpointer data)
99 {
100 #ifndef G_OS_WIN32
101 kill (parent_pid, SIGUSR1);
102 #endif
103 return G_SOURCE_REMOVE;
104 }
105  
106 static int
107 child_main (int argc, char *argv[])
108 {
109 GMappedFile *map;
110 GMainLoop *loop;
111  
112 parent_pid = atoi (argv[2]);
113 map = map_or_die (filename, FALSE);
114  
115 #ifndef G_OS_WIN32
116 signal (SIGUSR1, handle_usr1);
117 #endif
118 loop = g_main_loop_new (NULL, FALSE);
119 g_idle_add (check_stop, loop);
120 g_idle_add (signal_parent, NULL);
121 g_main_loop_run (loop);
122  
123 g_message ("test_child_private: received parent signal");
124  
125 write_or_die (childname,
126 g_mapped_file_get_contents (map),
127 g_mapped_file_get_length (map));
128  
129 signal_parent (NULL);
130  
131 return 0;
132 }
133  
134 static void
135 test_mapping (void)
136 {
137 GMappedFile *map;
138  
139 write_or_die (filename, "ABC", -1);
140  
141 map = map_or_die (filename, FALSE);
142 g_assert (g_mapped_file_get_length (map) == 3);
143 g_mapped_file_free (map);
144  
145 map = map_or_die (filename, TRUE);
146 g_assert (g_mapped_file_get_length (map) == 3);
147 g_mapped_file_free (map);
148 g_message ("test_mapping: ok");
149 }
150  
151 static void
152 test_private (void)
153 {
154 GError *error = NULL;
155 GMappedFile *map;
156 gchar *buffer;
157 gsize len;
158  
159 write_or_die (filename, "ABC", -1);
160 map = map_or_die (filename, TRUE);
161  
162 buffer = (gchar *)g_mapped_file_get_contents (map);
163 buffer[0] = '1';
164 buffer[1] = '2';
165 buffer[2] = '3';
166 g_mapped_file_free (map);
167  
168 if (!g_file_get_contents (filename, &buffer, &len, &error))
169 {
170 g_print ("failed to read '%s': %s\n",
171 displayname, error->message);
172 exit (1);
173  
174 }
175 g_assert (len == 3);
176 g_assert (strcmp (buffer, "ABC") == 0);
177 g_free (buffer);
178  
179 g_message ("test_private: ok");
180 }
181  
182 static void
183 test_child_private (gchar *argv0)
184 {
185 GError *error = NULL;
186 GMappedFile *map;
187 gchar *buffer;
188 gsize len;
189 gchar *child_argv[4];
190 GPid child_pid;
191 GMainLoop *loop;
192 gchar pid[100];
193  
194 #ifdef G_OS_WIN32
195 g_remove ("STOP");
196 g_assert (!g_file_test ("STOP", G_FILE_TEST_EXISTS));
197 #endif
198  
199 write_or_die (filename, "ABC", -1);
200 map = map_or_die (filename, TRUE);
201  
202 #ifndef G_OS_WIN32
203 signal (SIGUSR1, handle_usr1);
204 #endif
205  
206 g_snprintf (pid, sizeof(pid), "%d", getpid ());
207 child_argv[0] = argv0;
208 child_argv[1] = "mapchild";
209 child_argv[2] = pid;
210 child_argv[3] = NULL;
211 if (!g_spawn_async (dir, child_argv, NULL,
212 0, NULL, NULL, &child_pid, &error))
213 {
214 g_print ("failed to spawn child: %s\n",
215 error->message);
216 exit (1);
217 }
218 g_message ("test_child_private: child spawned");
219  
220 #ifndef G_OS_WIN32
221 loop = g_main_loop_new (NULL, FALSE);
222 g_idle_add (check_stop, loop);
223 g_main_loop_run (loop);
224 stop = FALSE;
225 #else
226 g_usleep (2000000);
227 #endif
228  
229 g_message ("test_child_private: received first child signal");
230  
231 buffer = (gchar *)g_mapped_file_get_contents (map);
232 buffer[0] = '1';
233 buffer[1] = '2';
234 buffer[2] = '3';
235 g_mapped_file_free (map);
236  
237 #ifndef G_OS_WIN32
238 kill (child_pid, SIGUSR1);
239 #else
240 g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
241 #endif
242  
243 #ifndef G_OS_WIN32
244 g_idle_add (check_stop, loop);
245 g_main_loop_run (loop);
246 #else
247 g_usleep (2000000);
248 #endif
249  
250 g_message ("test_child_private: received second child signal");
251  
252 if (!g_file_get_contents (childname, &buffer, &len, &error))
253 {
254 gchar *name;
255  
256 name = g_filename_display_name (childname);
257 g_print ("failed to read '%s': %s\n", name, error->message);
258 exit (1);
259 }
260 g_assert (len == 3);
261 g_assert (strcmp (buffer, "ABC") == 0);
262 g_free (buffer);
263  
264 g_message ("test_child_private: ok");
265 }
266  
267 static int
268 parent_main (int argc,
269 char *argv[])
270 {
271 /* test mapping with various flag combinations */
272 test_mapping ();
273  
274 /* test private modification */
275 test_private ();
276  
277 /* test multiple clients, non-shared */
278 test_child_private (argv[0]);
279  
280 return 0;
281 }
282  
283 int
284 main (int argc,
285 char *argv[])
286 {
287 int ret;
288 #ifndef G_OS_WIN32
289 sigset_t sig_mask, old_mask;
290  
291 sigemptyset (&sig_mask);
292 sigaddset (&sig_mask, SIGUSR1);
293 if (sigprocmask (SIG_UNBLOCK, &sig_mask, &old_mask) == 0)
294 {
295 if (sigismember (&old_mask, SIGUSR1))
296 g_message ("SIGUSR1 was blocked, unblocking it");
297 }
298 #endif
299  
300 dir = g_get_current_dir ();
301 filename = g_build_filename (dir, "maptest", NULL);
302 displayname = g_filename_display_name (filename);
303 childname = g_build_filename (dir, "mapchild", NULL);
304  
305 if (argc > 1)
306 ret = child_main (argc, argv);
307 else
308 ret = parent_main (argc, argv);
309  
310 g_free (childname);
311 g_free (filename);
312 g_free (displayname);
313 g_free (dir);
314  
315 return ret;
316 }