nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 2000 Tor Lillqvist |
||
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 | |||
18 | /* A test program for the main loop and IO channel code. |
||
19 | * Just run it. Optional parameter is number of sub-processes. |
||
20 | */ |
||
21 | |||
22 | #undef G_DISABLE_ASSERT |
||
23 | #undef G_LOG_DOMAIN |
||
24 | |||
25 | #include "config.h" |
||
26 | |||
27 | #include <glib.h> |
||
28 | |||
29 | #include <stdio.h> |
||
30 | #include <stdlib.h> |
||
31 | #include <math.h> |
||
32 | #include <time.h> |
||
33 | |||
34 | #ifdef G_OS_WIN32 |
||
35 | #include <io.h> |
||
36 | #include <fcntl.h> |
||
37 | #include <process.h> |
||
38 | #define STRICT |
||
39 | #include <windows.h> |
||
40 | #define pipe(fds) _pipe(fds, 4096, _O_BINARY) |
||
41 | #endif |
||
42 | |||
43 | #ifdef G_OS_UNIX |
||
44 | #include <unistd.h> |
||
45 | #endif |
||
46 | |||
47 | static int nrunning; |
||
48 | static GMainLoop *main_loop; |
||
49 | |||
50 | #define BUFSIZE 5000 /* Larger than the circular buffer in |
||
51 | * giowin32.c on purpose. |
||
52 | */ |
||
53 | |||
54 | static int nkiddies; |
||
55 | |||
56 | static struct { |
||
57 | int fd; |
||
58 | int seq; |
||
59 | } *seqtab; |
||
60 | |||
61 | static GIOError |
||
62 | read_all (int fd, |
||
63 | GIOChannel *channel, |
||
64 | char *buffer, |
||
65 | guint nbytes, |
||
66 | guint *bytes_read) |
||
67 | { |
||
68 | guint left = nbytes; |
||
69 | gsize nb; |
||
70 | GIOError error = G_IO_ERROR_NONE; |
||
71 | char *bufp = buffer; |
||
72 | |||
73 | /* g_io_channel_read() doesn't necessarily return all the |
||
74 | * data we want at once. |
||
75 | */ |
||
76 | *bytes_read = 0; |
||
77 | while (left) |
||
78 | { |
||
79 | error = g_io_channel_read (channel, bufp, left, &nb); |
||
80 | |||
81 | if (error != G_IO_ERROR_NONE) |
||
82 | { |
||
83 | g_print ("gio-test: ...from %d: %d\n", fd, error); |
||
84 | if (error == G_IO_ERROR_AGAIN) |
||
85 | continue; |
||
86 | break; |
||
87 | } |
||
88 | if (nb == 0) |
||
89 | return error; |
||
90 | left -= nb; |
||
91 | bufp += nb; |
||
92 | *bytes_read += nb; |
||
93 | } |
||
94 | return error; |
||
95 | } |
||
96 | |||
97 | static void |
||
98 | shutdown_source (gpointer data) |
||
99 | { |
||
100 | if (g_source_remove (*(guint *) data)) |
||
101 | { |
||
102 | nrunning--; |
||
103 | if (nrunning == 0) |
||
104 | g_main_loop_quit (main_loop); |
||
105 | } |
||
106 | } |
||
107 | |||
108 | static gboolean |
||
109 | recv_message (GIOChannel *channel, |
||
110 | GIOCondition cond, |
||
111 | gpointer data) |
||
112 | { |
||
113 | gint fd = g_io_channel_unix_get_fd (channel); |
||
114 | gboolean retval = TRUE; |
||
115 | |||
116 | #ifdef VERBOSE |
||
117 | g_print ("gio-test: ...from %d:%s%s%s%s\n", fd, |
||
118 | (cond & G_IO_ERR) ? " ERR" : "", |
||
119 | (cond & G_IO_HUP) ? " HUP" : "", |
||
120 | (cond & G_IO_IN) ? " IN" : "", |
||
121 | (cond & G_IO_PRI) ? " PRI" : ""); |
||
122 | #endif |
||
123 | |||
124 | if (cond & (G_IO_ERR | G_IO_HUP)) |
||
125 | { |
||
126 | shutdown_source (data); |
||
127 | retval = FALSE; |
||
128 | } |
||
129 | |||
130 | if (cond & G_IO_IN) |
||
131 | { |
||
132 | char buf[BUFSIZE]; |
||
133 | guint nbytes; |
||
134 | guint nb; |
||
135 | int i, j, seq; |
||
136 | GIOError error; |
||
137 | |||
138 | error = read_all (fd, channel, (gchar *) &seq, sizeof (seq), &nb); |
||
139 | if (error == G_IO_ERROR_NONE) |
||
140 | { |
||
141 | if (nb == 0) |
||
142 | { |
||
143 | #ifdef VERBOSE |
||
144 | g_print ("gio-test: ...from %d: EOF\n", fd); |
||
145 | #endif |
||
146 | shutdown_source (data); |
||
147 | return FALSE; |
||
148 | } |
||
149 | |||
150 | g_assert (nb == sizeof (nbytes)); |
||
151 | |||
152 | for (i = 0; i < nkiddies; i++) |
||
153 | if (seqtab[i].fd == fd) |
||
154 | { |
||
155 | g_assert_cmpint (seq, ==, seqtab[i].seq); |
||
156 | seqtab[i].seq++; |
||
157 | break; |
||
158 | } |
||
159 | |||
160 | error = read_all (fd, channel, (gchar *) &nbytes, sizeof (nbytes), &nb); |
||
161 | } |
||
162 | |||
163 | if (error != G_IO_ERROR_NONE) |
||
164 | return FALSE; |
||
165 | |||
166 | if (nb == 0) |
||
167 | { |
||
168 | #ifdef VERBOSE |
||
169 | g_print ("gio-test: ...from %d: EOF\n", fd); |
||
170 | #endif |
||
171 | shutdown_source (data); |
||
172 | return FALSE; |
||
173 | } |
||
174 | |||
175 | g_assert (nb == sizeof (nbytes)); |
||
176 | |||
177 | g_assert_cmpint (nbytes, <, BUFSIZE); |
||
178 | g_assert (nbytes >= 0 && nbytes < BUFSIZE); |
||
179 | #ifdef VERBOSE |
||
180 | g_print ("gio-test: ...from %d: %d bytes\n", fd, nbytes); |
||
181 | #endif |
||
182 | if (nbytes > 0) |
||
183 | { |
||
184 | error = read_all (fd, channel, buf, nbytes, &nb); |
||
185 | |||
186 | if (error != G_IO_ERROR_NONE) |
||
187 | return FALSE; |
||
188 | |||
189 | if (nb == 0) |
||
190 | { |
||
191 | #ifdef VERBOSE |
||
192 | g_print ("gio-test: ...from %d: EOF\n", fd); |
||
193 | #endif |
||
194 | shutdown_source (data); |
||
195 | return FALSE; |
||
196 | } |
||
197 | |||
198 | for (j = 0; j < nbytes; j++) |
||
199 | g_assert (buf[j] == ' ' + ((nbytes + j) % 95)); |
||
200 | #ifdef VERBOSE |
||
201 | g_print ("gio-test: ...from %d: OK\n", fd); |
||
202 | #endif |
||
203 | } |
||
204 | } |
||
205 | return retval; |
||
206 | } |
||
207 | |||
208 | #ifdef G_OS_WIN32 |
||
209 | |||
210 | static gboolean |
||
211 | recv_windows_message (GIOChannel *channel, |
||
212 | GIOCondition cond, |
||
213 | gpointer data) |
||
214 | { |
||
215 | GIOError error; |
||
216 | MSG msg; |
||
217 | guint nb; |
||
218 | |||
219 | while (1) |
||
220 | { |
||
221 | error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb); |
||
222 | |||
223 | if (error != G_IO_ERROR_NONE) |
||
224 | { |
||
225 | g_print ("gio-test: ...reading Windows message: G_IO_ERROR_%s\n", |
||
226 | (error == G_IO_ERROR_AGAIN ? "AGAIN" : |
||
227 | (error == G_IO_ERROR_INVAL ? "INVAL" : |
||
228 | (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???")))); |
||
229 | if (error == G_IO_ERROR_AGAIN) |
||
230 | continue; |
||
231 | } |
||
232 | break; |
||
233 | } |
||
234 | |||
235 | g_print ("gio-test: ...Windows message for %#x: %d,%d,%d\n", |
||
236 | msg.hwnd, msg.message, msg.wParam, msg.lParam); |
||
237 | |||
238 | return TRUE; |
||
239 | } |
||
240 | |||
241 | LRESULT CALLBACK |
||
242 | window_procedure (HWND hwnd, |
||
243 | UINT message, |
||
244 | WPARAM wparam, |
||
245 | LPARAM lparam) |
||
246 | { |
||
247 | g_print ("gio-test: window_procedure for %#x: %d,%d,%d\n", |
||
248 | hwnd, message, wparam, lparam); |
||
249 | return DefWindowProc (hwnd, message, wparam, lparam); |
||
250 | } |
||
251 | |||
252 | #endif |
||
253 | |||
254 | int |
||
255 | main (int argc, |
||
256 | char **argv) |
||
257 | { |
||
258 | if (argc < 3) |
||
259 | { |
||
260 | /* Parent */ |
||
261 | |||
262 | GIOChannel *my_read_channel; |
||
263 | gchar *cmdline; |
||
264 | guint *id; |
||
265 | int i; |
||
266 | #ifdef G_OS_WIN32 |
||
267 | GTimeVal start, end; |
||
268 | GPollFD pollfd; |
||
269 | int pollresult; |
||
270 | ATOM klass; |
||
271 | static WNDCLASS wcl; |
||
272 | HWND hwnd; |
||
273 | GIOChannel *windows_messages_channel; |
||
274 | #endif |
||
275 | |||
276 | nkiddies = (argc == 1 ? 1 : atoi(argv[1])); |
||
277 | seqtab = g_malloc (nkiddies * 2 * sizeof (int)); |
||
278 | |||
279 | #ifdef G_OS_WIN32 |
||
280 | wcl.style = 0; |
||
281 | wcl.lpfnWndProc = window_procedure; |
||
282 | wcl.cbClsExtra = 0; |
||
283 | wcl.cbWndExtra = 0; |
||
284 | wcl.hInstance = GetModuleHandle (NULL); |
||
285 | wcl.hIcon = NULL; |
||
286 | wcl.hCursor = NULL; |
||
287 | wcl.hbrBackground = NULL; |
||
288 | wcl.lpszMenuName = NULL; |
||
289 | wcl.lpszClassName = "gio-test"; |
||
290 | |||
291 | klass = RegisterClass (&wcl); |
||
292 | |||
293 | if (!klass) |
||
294 | { |
||
295 | g_print ("gio-test: RegisterClass failed\n"); |
||
296 | exit (1); |
||
297 | } |
||
298 | |||
299 | hwnd = CreateWindow (MAKEINTATOM(klass), "gio-test", 0, 0, 0, 10, 10, |
||
300 | NULL, NULL, wcl.hInstance, NULL); |
||
301 | if (!hwnd) |
||
302 | { |
||
303 | g_print ("gio-test: CreateWindow failed\n"); |
||
304 | exit (1); |
||
305 | } |
||
306 | |||
307 | windows_messages_channel = g_io_channel_win32_new_messages ((guint)hwnd); |
||
308 | g_io_add_watch (windows_messages_channel, G_IO_IN, recv_windows_message, 0); |
||
309 | #endif |
||
310 | |||
311 | for (i = 0; i < nkiddies; i++) |
||
312 | { |
||
313 | int pipe_to_sub[2], pipe_from_sub[2]; |
||
314 | |||
315 | if (pipe (pipe_to_sub) == -1 || |
||
316 | pipe (pipe_from_sub) == -1) |
||
317 | perror ("pipe"), exit (1); |
||
318 | |||
319 | seqtab[i].fd = pipe_from_sub[0]; |
||
320 | seqtab[i].seq = 0; |
||
321 | |||
322 | my_read_channel = g_io_channel_unix_new (pipe_from_sub[0]); |
||
323 | |||
324 | id = g_new (guint, 1); |
||
325 | *id = |
||
326 | g_io_add_watch (my_read_channel, |
||
327 | G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, |
||
328 | recv_message, |
||
329 | id); |
||
330 | |||
331 | nrunning++; |
||
332 | |||
333 | #ifdef G_OS_WIN32 |
||
334 | cmdline = g_strdup_printf ("%d:%d:%d", |
||
335 | pipe_to_sub[0], |
||
336 | pipe_from_sub[1], |
||
337 | hwnd); |
||
338 | _spawnl (_P_NOWAIT, argv[0], argv[0], "--child", cmdline, NULL); |
||
339 | #else |
||
340 | cmdline = g_strdup_printf ("%s --child %d:%d &", argv[0], |
||
341 | pipe_to_sub[0], pipe_from_sub[1]); |
||
342 | |||
343 | system (cmdline); |
||
344 | g_free (cmdline); |
||
345 | #endif |
||
346 | close (pipe_to_sub[0]); |
||
347 | close (pipe_from_sub [1]); |
||
348 | |||
349 | #ifdef G_OS_WIN32 |
||
350 | g_get_current_time (&start); |
||
351 | g_io_channel_win32_make_pollfd (my_read_channel, G_IO_IN, &pollfd); |
||
352 | pollresult = g_io_channel_win32_poll (&pollfd, 1, 100); |
||
353 | g_get_current_time (&end); |
||
354 | if (end.tv_usec < start.tv_usec) |
||
355 | end.tv_sec--, end.tv_usec += 1000000; |
||
356 | g_print ("gio-test: had to wait %ld.%03ld s, result:%d\n", |
||
357 | end.tv_sec - start.tv_sec, |
||
358 | (end.tv_usec - start.tv_usec) / 1000, |
||
359 | pollresult); |
||
360 | #endif |
||
361 | g_io_channel_unref (my_read_channel); |
||
362 | } |
||
363 | |||
364 | main_loop = g_main_loop_new (NULL, FALSE); |
||
365 | |||
366 | g_main_loop_run (main_loop); |
||
367 | |||
368 | g_main_loop_unref (main_loop); |
||
369 | g_free (seqtab); |
||
370 | g_free (id); |
||
371 | } |
||
372 | else if (argc == 3) |
||
373 | { |
||
374 | /* Child */ |
||
375 | |||
376 | int readfd, writefd; |
||
377 | #ifdef G_OS_WIN32 |
||
378 | HWND hwnd; |
||
379 | #endif |
||
380 | int i, j; |
||
381 | char buf[BUFSIZE]; |
||
382 | int buflen; |
||
383 | GTimeVal tv; |
||
384 | int n; |
||
385 | |||
386 | g_get_current_time (&tv); |
||
387 | |||
388 | sscanf (argv[2], "%d:%d%n", &readfd, &writefd, &n); |
||
389 | |||
390 | #ifdef G_OS_WIN32 |
||
391 | sscanf (argv[2] + n, ":%d", &hwnd); |
||
392 | #endif |
||
393 | |||
394 | srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4)); |
||
395 | |||
396 | for (i = 0; i < 20 + rand() % 20; i++) |
||
397 | { |
||
398 | g_usleep (100 + (rand() % 10) * 5000); |
||
399 | buflen = rand() % BUFSIZE; |
||
400 | for (j = 0; j < buflen; j++) |
||
401 | buf[j] = ' ' + ((buflen + j) % 95); |
||
402 | #ifdef VERBOSE |
||
403 | g_print ("gio-test: child writing %d+%d bytes to %d\n", |
||
404 | (int)(sizeof(i) + sizeof(buflen)), buflen, writefd); |
||
405 | #endif |
||
406 | write (writefd, &i, sizeof (i)); |
||
407 | write (writefd, &buflen, sizeof (buflen)); |
||
408 | write (writefd, buf, buflen); |
||
409 | |||
410 | #ifdef G_OS_WIN32 |
||
411 | if (rand() % 100 < 5) |
||
412 | { |
||
413 | int msg = WM_USER + (rand() % 100); |
||
414 | WPARAM wparam = rand (); |
||
415 | LPARAM lparam = rand (); |
||
416 | g_print ("gio-test: child posting message %d,%d,%d to %#x\n", |
||
417 | msg, wparam, lparam, hwnd); |
||
418 | PostMessage (hwnd, msg, wparam, lparam); |
||
419 | } |
||
420 | #endif |
||
421 | } |
||
422 | #ifdef VERBOSE |
||
423 | g_print ("gio-test: child exiting, closing %d\n", writefd); |
||
424 | #endif |
||
425 | close (writefd); |
||
426 | } |
||
427 | else |
||
428 | g_print ("Huh?\n"); |
||
429 | |||
430 | return 0; |
||
431 | } |
||
432 |