aboutsummaryrefslogtreecommitdiff
path: root/src/lib/eventloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eventloop.c')
-rw-r--r--src/lib/eventloop.c792
1 files changed, 400 insertions, 392 deletions
diff --git a/src/lib/eventloop.c b/src/lib/eventloop.c
index a1f8d44b..6f5595e6 100644
--- a/src/lib/eventloop.c
+++ b/src/lib/eventloop.c
@@ -55,11 +55,11 @@ struct GNUNET_GTK_MainLoop
55 * Initial task to run to setup the system. 55 * Initial task to run to setup the system.
56 */ 56 */
57 GNUNET_SCHEDULER_Task main_task; 57 GNUNET_SCHEDULER_Task main_task;
58 58
59 /** 59 /**
60 * Builder for the main window. 60 * Builder for the main window.
61 */ 61 */
62 GtkBuilder *builder; 62 GtkBuilder *builder;
63 63
64 /** 64 /**
65 * Gib's Main loop. 65 * Gib's Main loop.
@@ -192,7 +192,7 @@ GNUNET_GTK_main_loop_quit (struct GNUNET_GTK_MainLoop *ml)
192 */ 192 */
193GObject * 193GObject *
194GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml, 194GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml,
195 const char *name) 195 const char *name)
196{ 196{
197 return gtk_builder_get_object (ml->builder, name); 197 return gtk_builder_get_object (ml->builder, name);
198} 198}
@@ -205,10 +205,10 @@ GNUNET_GTK_main_loop_get_object (struct GNUNET_GTK_MainLoop *ml,
205 * @param tc scheduler context 205 * @param tc scheduler context
206 */ 206 */
207static void 207static void
208dispatch_gtk_task (void *cls, 208dispatch_gtk_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
209 const struct GNUNET_SCHEDULER_TaskContext *tc)
210{ 209{
211 struct GNUNET_GTK_MainLoop *ml = cls; 210 struct GNUNET_GTK_MainLoop *ml = cls;
211
212 g_main_context_dispatch (ml->gmc); 212 g_main_context_dispatch (ml->gmc);
213} 213}
214 214
@@ -220,8 +220,7 @@ dispatch_gtk_task (void *cls,
220 * @param new_size desired size of the cached poll array 220 * @param new_size desired size of the cached poll array
221 */ 221 */
222static void 222static void
223resize_cached_poll_array (struct GNUNET_GTK_MainLoop *ml, 223resize_cached_poll_array (struct GNUNET_GTK_MainLoop *ml, guint new_size)
224 guint new_size)
225{ 224{
226 if (NULL == ml->cached_poll_array) 225 if (NULL == ml->cached_poll_array)
227 ml->cached_poll_array = g_new (GPollFD, new_size); 226 ml->cached_poll_array = g_new (GPollFD, new_size);
@@ -235,16 +234,14 @@ resize_cached_poll_array (struct GNUNET_GTK_MainLoop *ml,
235 * Dummy task to keep our scheduler running. 234 * Dummy task to keep our scheduler running.
236 */ 235 */
237static void 236static void
238keepalive_task (void *cls, 237keepalive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
239 const struct GNUNET_SCHEDULER_TaskContext *tc)
240{ 238{
241 struct GNUNET_GTK_MainLoop *ml = cls; 239 struct GNUNET_GTK_MainLoop *ml = cls;
242 240
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dummy task was scheduled\n");
244 "Dummy task was scheduled\n"); 242 ml->dummy_task =
245 ml->dummy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 243 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
246 &keepalive_task, 244 &keepalive_task, ml);
247 ml);
248} 245}
249 246
250 247
@@ -267,8 +264,7 @@ keepalive_task (void *cls,
267 * @return number of selected sockets, GNUNET_SYSERR on error 264 * @return number of selected sockets, GNUNET_SYSERR on error
268 */ 265 */
269static int 266static int
270gnunet_gtk_select (void *cls, 267gnunet_gtk_select (void *cls, struct GNUNET_NETWORK_FDSet *rfds,
271 struct GNUNET_NETWORK_FDSet *rfds,
272 struct GNUNET_NETWORK_FDSet *wfds, 268 struct GNUNET_NETWORK_FDSet *wfds,
273 struct GNUNET_NETWORK_FDSet *efds, 269 struct GNUNET_NETWORK_FDSet *efds,
274 const struct GNUNET_TIME_Relative timeout) 270 const struct GNUNET_TIME_Relative timeout)
@@ -299,10 +295,7 @@ gnunet_gtk_select (void *cls,
299#endif 295#endif
300 296
301 if (TRUE != g_main_loop_is_running (ml->gml)) 297 if (TRUE != g_main_loop_is_running (ml->gml))
302 return GNUNET_NETWORK_socket_select (rfds, 298 return GNUNET_NETWORK_socket_select (rfds, wfds, efds, timeout);
303 wfds,
304 efds,
305 timeout);
306 if (NULL != rfds) 299 if (NULL != rfds)
307 FD_COPY (&rfds->sds, &aread); 300 FD_COPY (&rfds->sds, &aread);
308 else 301 else
@@ -340,249 +333,260 @@ gnunet_gtk_select (void *cls,
340#if !WINDOWS 333#if !WINDOWS
341 fd_counter = 0; 334 fd_counter = 0;
342 for (i = 0; i < max_nfds; i++) 335 for (i = 0; i < max_nfds; i++)
343 { 336 {
344 int isset[3]; 337 int isset[3];
345 338
346 isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds); 339 isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds);
347 isset[1] = (wfds == NULL) ? 0 : FD_ISSET (i, &wfds->sds); 340 isset[1] = (wfds == NULL) ? 0 : FD_ISSET (i, &wfds->sds);
348 isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds); 341 isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds);
349 if ((! isset[0]) && (! isset[1]) && (! isset[2])) 342 if ((!isset[0]) && (!isset[1]) && (!isset[2]))
350 continue; 343 continue;
351 if (fd_counter >= ml->cached_poll_array_size) 344 if (fd_counter >= ml->cached_poll_array_size)
352 resize_cached_poll_array (ml, ml->cached_poll_array_size * 2); 345 resize_cached_poll_array (ml, ml->cached_poll_array_size * 2);
353 ml->cached_poll_array[fd_counter].fd = i; 346 ml->cached_poll_array[fd_counter].fd = i;
354 ml->cached_poll_array[fd_counter].events 347 ml->cached_poll_array[fd_counter].events =
355 = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0) 348 (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0) | (isset[1] ? G_IO_OUT |
356 | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) 349 G_IO_ERR : 0) |
357 | (isset[2] ? G_IO_ERR : 0); 350 (isset[2] ? G_IO_ERR : 0);
358 fd_counter++; 351 fd_counter++;
359 } 352 }
360#else 353#else
361 /* FIXME: why while(1) here!? */ 354 /* FIXME: why while(1) here!? */
362 while (1) 355 while (1)
356 {
357 struct GNUNET_CONTAINER_SList_Iterator *t;
358
359 fd_counter = 0;
360 /* We might overshoot a little, but that won't hurt very much */
361 int need_nfds =
362 (rfds->sds.fd_count + rfds->sds.fd_count + rfds->sds.fd_count >
363 0 ? 3 : 0) + (rfds ==
364 NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles))
365 + (wfds == NULL ? 0 : 1) + 1;
366 if (need_nfds >= ml->cached_poll_array_size)
367 resize_cached_poll_array (ml, need_nfds * 2);
368 /* Since there are also gmainloop's own fds, just need_nfds won't be
369 * enough, so make it twice as long.
370 */
371 if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles))
372 {
373 ml->read_array =
374 GNUNET_realloc (ml->read_array,
375 GNUNET_CONTAINER_slist_count (rfds->handles) *
376 sizeof (struct GNUNET_DISK_FileHandle *));
377 ml->read_array_length = GNUNET_CONTAINER_slist_count (rfds->handles);
378 }
379 if (rfds != NULL)
363 { 380 {
364 struct GNUNET_CONTAINER_SList_Iterator *t; 381 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles), i = 0;
365 382 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
366 fd_counter = 0; 383 GNUNET_CONTAINER_slist_next (t), i += 1)
367 /* We might overshoot a little, but that won't hurt very much */ 384 {
368 int need_nfds = (rfds->sds.fd_count + rfds->sds.fd_count + rfds->sds.fd_count > 0 ? 3 : 0) 385 struct GNUNET_DISK_FileHandle *fh =
369 + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles)) 386 GNUNET_CONTAINER_slist_get (t, NULL);
370 + (wfds == NULL ? 0 : 1) 387 if (fh->type == GNUNET_PIPE)
371 + 1; 388 {
372 if (need_nfds >= ml->cached_poll_array_size) 389 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
373 resize_cached_poll_array (ml, need_nfds * 2); 390 {
374 /* Since there are also gmainloop's own fds, just need_nfds won't be 391 DWORD error_code = GetLastError ();
375 * enough, so make it twice as long. 392
376 */ 393 if (error_code == ERROR_IO_PENDING)
377 if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles)) 394 {
378 {
379 ml->read_array = GNUNET_realloc (ml->read_array,
380 GNUNET_CONTAINER_slist_count (rfds->handles) * sizeof (struct GNUNET_DISK_FileHandle *));
381 ml->read_array_length = GNUNET_CONTAINER_slist_count (rfds->handles);
382 }
383 if (rfds != NULL)
384 {
385 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles), i = 0;
386 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
387 GNUNET_CONTAINER_slist_next (t), i += 1)
388 {
389 struct GNUNET_DISK_FileHandle *fh = GNUNET_CONTAINER_slist_get (t, NULL);
390 if (fh->type == GNUNET_PIPE)
391 {
392 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
393 {
394 DWORD error_code = GetLastError();
395 if (error_code == ERROR_IO_PENDING)
396 {
397#if DEBUG_EVENTLOOP 395#if DEBUG_EVENTLOOP
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 "Adding the pipe's 0x%x overlapped event to the array as %d\n", 397 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
400 fh->h, nhandles); 398 fh->h, nhandles);
401#endif 399#endif
402 ml->cached_poll_array[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent; 400 ml->cached_poll_array[fd_counter].fd =
403 /* On W32 .events makes no sense - g_poll will just OR its 401 (intptr_t) fh->oOverlapRead->hEvent;
404 * contents into .revents when the .fd event fires. 402 /* On W32 .events makes no sense - g_poll will just OR its
405 * So we'll use it in the way that suits us the best. 403 * contents into .revents when the .fd event fires.
406 */ 404 * So we'll use it in the way that suits us the best.
407 ml->cached_poll_array[fd_counter].events = G_IO_IN; 405 */
408 fd_counter += 1; 406 ml->cached_poll_array[fd_counter].events = G_IO_IN;
409 ml->read_array[read_handles] = fh; 407 fd_counter += 1;
410 read_handles += 1; 408 ml->read_array[read_handles] = fh;
411 } 409 read_handles += 1;
412 else 410 }
413 { 411 else
414 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventReadReady; 412 {
415 ml->cached_poll_array[fd_counter].events = G_IO_HUP; 413 ml->cached_poll_array[fd_counter].fd =
416 fd_counter += 1; 414 (intptr_t) ml->hEventReadReady;
417 ml->read_array[read_handles] = fh; 415 ml->cached_poll_array[fd_counter].events = G_IO_HUP;
418 read_handles += 1; 416 fd_counter += 1;
419 } 417 ml->read_array[read_handles] = fh;
420 } 418 read_handles += 1;
421 else 419 }
422 { 420 }
421 else
422 {
423#if DEBUG_EVENTLOOP 423#if DEBUG_EVENTLOOP
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "Adding the read ready event to the array as %d\n", 425 "Adding the read ready event to the array as %d\n",
426 nhandles); 426 nhandles);
427#endif 427#endif
428 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventReadReady; 428 ml->cached_poll_array[fd_counter].fd =
429 ml->cached_poll_array[fd_counter].events = G_IO_IN; 429 (intptr_t) ml->hEventReadReady;
430 fd_counter += 1; 430 ml->cached_poll_array[fd_counter].events = G_IO_IN;
431 ml->read_array[read_handles] = fh; 431 fd_counter += 1;
432 read_handles += 1; 432 ml->read_array[read_handles] = fh;
433 } 433 read_handles += 1;
434 } 434 }
435 else 435 }
436 { 436 else
437 GNUNET_CONTAINER_slist_add (ml->handles_read, 437 {
438 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, 438 GNUNET_CONTAINER_slist_add (ml->handles_read,
439 fh, sizeof (struct GNUNET_DISK_FileHandle)); 439 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
440 pre_ret++; 440 fh,
441 } 441 sizeof (struct GNUNET_DISK_FileHandle));
442 } 442 pre_ret++;
443 } 443 }
444 if ( (wfds != NULL) && (GNUNET_CONTAINER_slist_count (wfds->handles) > 0) ) 444 }
445 { 445 }
446 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventPipeWrite; 446 if ((wfds != NULL) && (GNUNET_CONTAINER_slist_count (wfds->handles) > 0))
447 ml->cached_poll_array[fd_counter].events = G_IO_OUT; 447 {
448 always_ready_write_fd = fd_counter; 448 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventPipeWrite;
449 fd_counter += 1; 449 ml->cached_poll_array[fd_counter].events = G_IO_OUT;
450 } 450 always_ready_write_fd = fd_counter;
451 if (efds != NULL) 451 fd_counter += 1;
452 { 452 }
453 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0; 453 if (efds != NULL)
454 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; 454 {
455 GNUNET_CONTAINER_slist_next (t), i += 1) 455 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
456 { 456 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
457 struct GNUNET_DISK_FileHandle *fh = GNUNET_CONTAINER_slist_get (t, NULL); 457 GNUNET_CONTAINER_slist_next (t), i += 1)
458 458 {
459 DWORD dwBytes; 459 struct GNUNET_DISK_FileHandle *fh =
460 if (fh->type == GNUNET_PIPE) 460 GNUNET_CONTAINER_slist_get (t, NULL);
461 { 461
462 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) 462 DWORD dwBytes;
463 { 463
464 GNUNET_CONTAINER_slist_add (ml->handles_except, 464 if (fh->type == GNUNET_PIPE)
465 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, 465 {
466 fh, sizeof (struct GNUNET_DISK_FileHandle)); 466 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
467 pre_ret++; 467 {
468 } 468 GNUNET_CONTAINER_slist_add (ml->handles_except,
469 } 469 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
470 } 470 fh,
471 } 471 sizeof (struct GNUNET_DISK_FileHandle));
472 GNUNET_CONTAINER_slist_iter_destroy (t); 472 pre_ret++;
473 473 }
474 if ( (rfds != NULL) && (rfds->sds.fd_count > 0) ) 474 }
475 { 475 }
476 }
477 GNUNET_CONTAINER_slist_iter_destroy (t);
478
479 if ((rfds != NULL) && (rfds->sds.fd_count > 0))
480 {
476#if DEBUG_EVENTLOOP 481#if DEBUG_EVENTLOOP
477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
478 "Adding the socket read event to the array as %d\n", 483 "Adding the socket read event to the array as %d\n",
479 fd_counter); 484 fd_counter);
480#endif 485#endif
481 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventRead; 486 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventRead;
482 ml->cached_poll_array[fd_counter].events = G_IO_IN; 487 ml->cached_poll_array[fd_counter].events = G_IO_IN;
483 for (i = 0; i < rfds->sds.fd_count; i++) 488 for (i = 0; i < rfds->sds.fd_count; i++)
484 WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE); 489 WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead,
485 fd_counter += 1; 490 FD_ACCEPT | FD_READ | FD_CLOSE);
486 sock_read = rfds->sds.fd_count; 491 fd_counter += 1;
487 } 492 sock_read = rfds->sds.fd_count;
488 if ( (wfds != NULL) && (wfds->sds.fd_count > 0) ) 493 }
489 { 494 if ((wfds != NULL) && (wfds->sds.fd_count > 0))
490 int wakeup = 0; 495 {
496 int wakeup = 0;
497
491#if DEBUG_EVENTLOOP 498#if DEBUG_EVENTLOOP
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
493 "Adding the socket write event to the array as %d\n", 500 "Adding the socket write event to the array as %d\n",
494 fd_counter); 501 fd_counter);
495#endif 502#endif
496 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventWrite; 503 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventWrite;
497 ml->cached_poll_array[fd_counter].events = G_IO_OUT; 504 ml->cached_poll_array[fd_counter].events = G_IO_OUT;
498 for (i = 0; i < wfds->sds.fd_count; i++) 505 for (i = 0; i < wfds->sds.fd_count; i++)
499 { 506 {
500 DWORD error; 507 DWORD error;
501 int status; 508 int status;
502 status = send (wfds->sds.fd_array[i], NULL, 0, 0); 509
503 error = GetLastError (); 510 status = send (wfds->sds.fd_array[i], NULL, 0, 0);
511 error = GetLastError ();
504#if DEBUG_EVENTLOOP 512#if DEBUG_EVENTLOOP
505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
506 "pre-send to the socket %d returned %d (%u)\n", 514 "pre-send to the socket %d returned %d (%u)\n", i, status,
507 i, status, error); 515 error);
508#endif 516#endif
509 if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)) 517 if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN))
510 wakeup = 1; 518 wakeup = 1;
511 WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, FD_WRITE | FD_CONNECT | FD_CLOSE); 519 WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite,
512 } 520 FD_WRITE | FD_CONNECT | FD_CLOSE);
513 if (wakeup) 521 }
514 SetEvent (ml->hEventWrite); 522 if (wakeup)
515 fd_counter += 1; 523 SetEvent (ml->hEventWrite);
516 sock_write = wfds->sds.fd_count; 524 fd_counter += 1;
517 } 525 sock_write = wfds->sds.fd_count;
518 if ( (efds != NULL) && (efds->sds.fd_count > 0) ) 526 }
519 { 527 if ((efds != NULL) && (efds->sds.fd_count > 0))
528 {
520#if DEBUG_EVENTLOOP 529#if DEBUG_EVENTLOOP
521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
522 "Adding the socket error event to the array as %d\n", 531 "Adding the socket error event to the array as %d\n",
523 fd_counter); 532 fd_counter);
524#endif 533#endif
525 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventException; 534 ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventException;
526 ml->cached_poll_array[fd_counter].events = G_IO_ERR; 535 ml->cached_poll_array[fd_counter].events = G_IO_ERR;
527 for (i = 0; i < efds->sds.fd_count; i++) 536 for (i = 0; i < efds->sds.fd_count; i++)
528 WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, FD_OOB | FD_CLOSE); 537 WSAEventSelect (efds->sds.fd_array[i], ml->hEventException,
529 fd_counter++; 538 FD_OOB | FD_CLOSE);
530 sock_err = efds->sds.fd_count; 539 fd_counter++;
531 } 540 sock_err = efds->sds.fd_count;
532 break;
533 } 541 }
542 break;
543 }
534 socks = sock_read + sock_write + sock_err; 544 socks = sock_read + sock_write + sock_err;
535#endif 545#endif
536 546
537 /* combine with Gtk events */ 547 /* combine with Gtk events */
538 g_main_context_prepare (ml->gmc, &max_priority); 548 g_main_context_prepare (ml->gmc, &max_priority);
539 while (1) 549 while (1)
540 { 550 {
541 need_gfds = g_main_context_query (ml->gmc, 551 need_gfds =
542 max_priority, 552 g_main_context_query (ml->gmc, max_priority, &delay,
543 &delay, 553 &ml->cached_poll_array[fd_counter],
544 &ml->cached_poll_array[fd_counter], 554 ml->cached_poll_array_size - fd_counter);
545 ml->cached_poll_array_size - fd_counter); 555 if (ml->cached_poll_array_size >= need_gfds + fd_counter)
546 if (ml->cached_poll_array_size >= need_gfds + fd_counter) 556 break;
547 break; 557 resize_cached_poll_array (ml, fd_counter + need_gfds);
548 resize_cached_poll_array (ml, 558 }
549 fd_counter + need_gfds);
550 }
551 559
552 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) 560 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
553 { 561 {
554 if (delay >= 0) 562 if (delay >= 0)
555 delay = GNUNET_MIN (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value, 563 delay =
556 delay); 564 GNUNET_MIN (timeout.rel_value /
557 else 565 GNUNET_TIME_UNIT_MILLISECONDS.rel_value, delay);
558 delay = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; 566 else
559 } 567 delay = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
568 }
560 569
561#if WINDOWS 570#if WINDOWS
562 if (pre_ret > 0) 571 if (pre_ret > 0)
563 { 572 {
564#if DEBUG_EVENTLOOP 573#if DEBUG_EVENTLOOP
565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre_ret is %d, setting delay to 0\n",
566 "pre_ret is %d, setting delay to 0\n", 575 pre_ret);
567 pre_ret);
568#endif 576#endif
569 delay = 0; 577 delay = 0;
570 } 578 }
571#endif 579#endif
572 580
573#if DEBUG_EVENTLOOP 581#if DEBUG_EVENTLOOP
574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
575 "We have %d of our FDs and %d of GMC ones, going to wait %6dms\n", 583 "We have %d of our FDs and %d of GMC ones, going to wait %6dms\n",
576 fd_counter, need_gfds, delay); 584 fd_counter, need_gfds, delay);
577#endif 585#endif
578 586
579 poll_result = g_poll (ml->cached_poll_array, 587 poll_result = g_poll (ml->cached_poll_array, fd_counter + need_gfds, delay);
580 fd_counter + need_gfds,
581 delay);
582#if DEBUG_EVENTLOOP 588#if DEBUG_EVENTLOOP
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result);
584 "g_poll returned : %d\n",
585 poll_result);
586#endif 590#endif
587 591
588 /* Take care of GUI events. 592 /* Take care of GUI events.
@@ -590,12 +594,11 @@ gnunet_gtk_select (void *cls,
590 * from within a task (currently we're not in a task, but in a select() call, remember) 594 * from within a task (currently we're not in a task, but in a select() call, remember)
591 * Startup reason is used to pass the scheduler sanity check. 595 * Startup reason is used to pass the scheduler sanity check.
592 */ 596 */
593 if (TRUE == g_main_context_check (ml->gmc, 597 if (TRUE ==
594 max_priority, 598 g_main_context_check (ml->gmc, max_priority,
595 &ml->cached_poll_array[fd_counter], 599 &ml->cached_poll_array[fd_counter], need_gfds))
596 need_gfds))
597 GNUNET_SCHEDULER_add_continuation (&dispatch_gtk_task, ml, 600 GNUNET_SCHEDULER_add_continuation (&dispatch_gtk_task, ml,
598 GNUNET_SCHEDULER_REASON_STARTUP); 601 GNUNET_SCHEDULER_REASON_STARTUP);
599 602
600 /* Now map back GNUnet scheduler events ... */ 603 /* Now map back GNUnet scheduler events ... */
601#if !WINDOWS 604#if !WINDOWS
@@ -606,167 +609,177 @@ gnunet_gtk_select (void *cls,
606 if (NULL != efds) 609 if (NULL != efds)
607 GNUNET_NETWORK_fdset_zero (efds); 610 GNUNET_NETWORK_fdset_zero (efds);
608 for (i = 0; i < fd_counter; i++) 611 for (i = 0; i < fd_counter; i++)
609 { 612 {
610 int set = 0; 613 int set = 0;
611 614
612 if ( (NULL != rfds) && 615 if ((NULL != rfds) &&
613 (set |= (FD_ISSET (ml->cached_poll_array[i].fd, &aread) && 616 (set |=
614 (0 != (ml->cached_poll_array[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)))))) 617 (FD_ISSET (ml->cached_poll_array[i].fd, &aread) &&
615 GNUNET_NETWORK_fdset_set_native (rfds, ml->cached_poll_array[i].fd); 618 (0 !=
616 if ( (NULL != wfds) && 619 (ml->
617 (set |= (FD_ISSET (ml->cached_poll_array[i].fd, &awrite) && 620 cached_poll_array[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))))))
618 (0 != (ml->cached_poll_array[i].revents & (G_IO_OUT | G_IO_ERR)))))) 621 GNUNET_NETWORK_fdset_set_native (rfds, ml->cached_poll_array[i].fd);
619 GNUNET_NETWORK_fdset_set_native (wfds, ml->cached_poll_array[i].fd); 622 if ((NULL != wfds) &&
620 if ( (NULL != efds) && 623 (set |=
621 (set |= (FD_ISSET (ml->cached_poll_array[i].fd, &aexcept) && 624 (FD_ISSET (ml->cached_poll_array[i].fd, &awrite) &&
622 (0 != (ml->cached_poll_array[i].revents & G_IO_ERR))))) 625 (0 != (ml->cached_poll_array[i].revents & (G_IO_OUT | G_IO_ERR))))))
623 GNUNET_NETWORK_fdset_set_native (efds, ml->cached_poll_array[i].fd); 626 GNUNET_NETWORK_fdset_set_native (wfds, ml->cached_poll_array[i].fd);
624 if (set) 627 if ((NULL != efds) &&
625 result++; 628 (set |=
626 } 629 (FD_ISSET (ml->cached_poll_array[i].fd, &aexcept) &&
630 (0 != (ml->cached_poll_array[i].revents & G_IO_ERR)))))
631 GNUNET_NETWORK_fdset_set_native (efds, ml->cached_poll_array[i].fd);
632 if (set)
633 result++;
634 }
627#else 635#else
628 if (socks > 0) 636 if (socks > 0)
629 { 637 {
630 struct timeval tvslice; 638 struct timeval tvslice;
631 tvslice.tv_sec = 0; 639
632 tvslice.tv_usec = 0; 640 tvslice.tv_sec = 0;
633 select_ret = select (max_nfds, &aread, &awrite, &aexcept, &tvslice); 641 tvslice.tv_usec = 0;
634 if (select_ret == -1) 642 select_ret = select (max_nfds, &aread, &awrite, &aexcept, &tvslice);
635 select_ret = 0; 643 if (select_ret == -1)
644 select_ret = 0;
636#if DEBUG_EVENTLOOP 645#if DEBUG_EVENTLOOP
637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret);
638 "select() returned %d\n",
639 select_ret);
640#endif 647#endif
641 } 648 }
642 if (always_ready_write_fd >= 0 && ml->cached_poll_array[always_ready_write_fd].revents & G_IO_OUT) 649 if (always_ready_write_fd >= 0 &&
643 { 650 ml->cached_poll_array[always_ready_write_fd].revents & G_IO_OUT)
644 GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles); 651 {
645 result += GNUNET_CONTAINER_slist_count (ml->handles_write); 652 GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles);
653 result += GNUNET_CONTAINER_slist_count (ml->handles_write);
646#if DEBUG_EVENTLOOP 654#if DEBUG_EVENTLOOP
647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n"); 655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
648#endif 656#endif
649 } 657 }
650 for (i = 0; i < read_handles; i++) 658 for (i = 0; i < read_handles; i++)
651 { 659 {
652 DWORD error; 660 DWORD error;
653 BOOL bret; 661 BOOL bret;
654 if (!(ml->cached_poll_array[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) 662
655 continue; 663 if (!(ml->cached_poll_array[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)))
656 SetLastError (0); 664 continue;
657 waitstatus = 0; 665 SetLastError (0);
658 bret = PeekNamedPipe (ml->read_array[i]->h, NULL, 0, NULL, &waitstatus, NULL); 666 waitstatus = 0;
659 error = GetLastError (); 667 bret =
668 PeekNamedPipe (ml->read_array[i]->h, NULL, 0, NULL, &waitstatus, NULL);
669 error = GetLastError ();
660#if DEBUG_EVENTLOOP 670#if DEBUG_EVENTLOOP
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", 672 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
663 i, ml->read_array[i]->h, bret, waitstatus, error); 673 i, ml->read_array[i]->h, bret, waitstatus, error);
664#endif 674#endif
665 if (bret == 0 || (ml->cached_poll_array[i].revents & G_IO_ERR)) 675 if (bret == 0 || (ml->cached_poll_array[i].revents & G_IO_ERR))
666 { 676 {
667 if (efds != NULL) 677 if (efds != NULL)
668 { 678 {
669 struct GNUNET_CONTAINER_SList_Iterator *t; 679 struct GNUNET_CONTAINER_SList_Iterator *t;
670 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0; 680
671 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; 681 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
672 GNUNET_CONTAINER_slist_next (t), i += 1) 682 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
673 { 683 GNUNET_CONTAINER_slist_next (t), i += 1)
674 struct GNUNET_DISK_FileHandle *fh = GNUNET_CONTAINER_slist_get (t, NULL); 684 {
675 if (fh == ml->read_array[i]) 685 struct GNUNET_DISK_FileHandle *fh =
676 { 686 GNUNET_CONTAINER_slist_get (t, NULL);
677 GNUNET_CONTAINER_slist_add (ml->handles_except, 687 if (fh == ml->read_array[i])
678 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, 688 {
679 fh, sizeof (struct GNUNET_DISK_FileHandle)); 689 GNUNET_CONTAINER_slist_add (ml->handles_except,
680 break; 690 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
681 } 691 fh,
682 } 692 sizeof (struct GNUNET_DISK_FileHandle));
683 GNUNET_CONTAINER_slist_iter_destroy (t); 693 break;
684 } 694 }
685 } 695 }
686 else if (waitstatus <= 0) 696 GNUNET_CONTAINER_slist_iter_destroy (t);
687 continue; 697 }
688 GNUNET_CONTAINER_slist_add (ml->handles_read, 698 }
689 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, 699 else if (waitstatus <= 0)
690 ml->read_array[i], sizeof (struct GNUNET_DISK_FileHandle)); 700 continue;
691 result += 1; 701 GNUNET_CONTAINER_slist_add (ml->handles_read,
702 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
703 ml->read_array[i],
704 sizeof (struct GNUNET_DISK_FileHandle));
705 result += 1;
692#if DEBUG_EVENTLOOP 706#if DEBUG_EVENTLOOP
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
694 "Added read Pipe 0x%x (0x%x)\n", 708 ml->read_array[i], ml->read_array[i]->h);
695 ml->read_array[i],
696 ml->read_array[i]->h);
697#endif 709#endif
698 } 710 }
699 waitstatus = WaitForSingleObject (ml->hEventWrite, 0); 711 waitstatus = WaitForSingleObject (ml->hEventWrite, 0);
700#if DEBUG_EVENTLOOP 712#if DEBUG_EVENTLOOP
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n",
702 "Wait for the write event returned %d\n", 714 waitstatus);
703 waitstatus);
704#endif 715#endif
705 if (waitstatus == WAIT_OBJECT_0) 716 if (waitstatus == WAIT_OBJECT_0)
717 {
718 for (i = 0; i < wfds->sds.fd_count; i++)
706 { 719 {
707 for (i = 0; i < wfds->sds.fd_count; i++) 720 DWORD error;
708 { 721 int status;
709 DWORD error; 722 int so_error = 0;
710 int status; 723 int sizeof_so_error = sizeof (so_error);
711 int so_error = 0; 724 int gso_result = getsockopt (wfds->sds.fd_array[i],
712 int sizeof_so_error = sizeof (so_error); 725 SOL_SOCKET, SO_ERROR,
713 int gso_result = getsockopt (wfds->sds.fd_array[i], 726 (char *) &so_error, &sizeof_so_error);
714 SOL_SOCKET, SO_ERROR, 727
715 (char *) &so_error, &sizeof_so_error); 728 status = send (wfds->sds.fd_array[i], NULL, 0, 0);
716 status = send (wfds->sds.fd_array[i], NULL, 0, 0); 729 error = GetLastError ();
717 error = GetLastError ();
718#if DEBUG_EVENTLOOP 730#if DEBUG_EVENTLOOP
719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 731 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
720 "send to the socket %d returned %d (%u)\n", 732 "send to the socket %d returned %d (%u)\n", i, status, error);
721 i, status, error);
722#endif 733#endif
723 if (status == 0 734 if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) ||
724 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) 735 (status == -1 && gso_result == 0 && error == WSAENOTCONN &&
725 || (status == -1 && gso_result == 0 && error == WSAENOTCONN && so_error == WSAECONNREFUSED)) 736 so_error == WSAECONNREFUSED))
726 { 737 {
727 FD_SET (wfds->sds.fd_array[i], &awrite); 738 FD_SET (wfds->sds.fd_array[i], &awrite);
728 result += 1; 739 result += 1;
729 } 740 }
730 }
731 } 741 }
742 }
732 if (rfds) 743 if (rfds)
744 {
745 struct GNUNET_CONTAINER_SList_Iterator *t;
746
747 for (i = 0; i < rfds->sds.fd_count; i++)
748 WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, 0);
749 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
750 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
751 GNUNET_CONTAINER_slist_next (t))
733 { 752 {
734 struct GNUNET_CONTAINER_SList_Iterator *t; 753 struct GNUNET_DISK_FileHandle *fh = GNUNET_CONTAINER_slist_get (t, NULL);
735 for (i = 0; i < rfds->sds.fd_count; i++) 754
736 WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, 0); 755 if (fh->type == GNUNET_PIPE)
737 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); 756 CancelIo (fh->h);
738 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
739 GNUNET_CONTAINER_slist_next (t))
740 {
741 struct GNUNET_DISK_FileHandle *fh = GNUNET_CONTAINER_slist_get (t, NULL);
742 if (fh->type == GNUNET_PIPE)
743 CancelIo (fh->h);
744 }
745 GNUNET_CONTAINER_slist_iter_destroy (t);
746 GNUNET_NETWORK_fdset_zero (rfds);
747 if (select_ret != -1 && socks > 0)
748 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, select_ret);
749 GNUNET_CONTAINER_slist_append (rfds->handles, ml->handles_read);
750 } 757 }
758 GNUNET_CONTAINER_slist_iter_destroy (t);
759 GNUNET_NETWORK_fdset_zero (rfds);
760 if (select_ret != -1 && socks > 0)
761 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, select_ret);
762 GNUNET_CONTAINER_slist_append (rfds->handles, ml->handles_read);
763 }
751 if (wfds) 764 if (wfds)
752 { 765 {
753 for (i = 0; i < wfds->sds.fd_count; i++) 766 for (i = 0; i < wfds->sds.fd_count; i++)
754 WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, 0); 767 WSAEventSelect (wfds->sds.fd_array[i], ml->hEventWrite, 0);
755 GNUNET_NETWORK_fdset_zero (wfds); 768 GNUNET_NETWORK_fdset_zero (wfds);
756 if (select_ret != -1 && socks > 0) 769 if (select_ret != -1 && socks > 0)
757 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, select_ret); 770 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, select_ret);
758 GNUNET_CONTAINER_slist_append (wfds->handles, ml->handles_write); 771 GNUNET_CONTAINER_slist_append (wfds->handles, ml->handles_write);
759 } 772 }
760 if (efds) 773 if (efds)
761 { 774 {
762 for (i = 0; i < efds->sds.fd_count; i++) 775 for (i = 0; i < efds->sds.fd_count; i++)
763 WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, 0); 776 WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, 0);
764 GNUNET_NETWORK_fdset_zero (efds); 777 GNUNET_NETWORK_fdset_zero (efds);
765 if (select_ret != -1 && socks > 0) 778 if (select_ret != -1 && socks > 0)
766 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, select_ret); 779 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, select_ret);
767 GNUNET_CONTAINER_slist_append (efds->handles, ml->handles_except); 780 GNUNET_CONTAINER_slist_append (efds->handles, ml->handles_except);
768 result += GNUNET_CONTAINER_slist_count (ml->handles_except); 781 result += GNUNET_CONTAINER_slist_count (ml->handles_except);
769 } 782 }
770 if (fd_counter > 0) 783 if (fd_counter > 0)
771 /* This is not accurate (select_ret counts write-ready sockets, 784 /* This is not accurate (select_ret counts write-ready sockets,
772 * and result does as well. Anything out there actually cares 785 * and result does as well. Anything out there actually cares
@@ -789,19 +802,18 @@ gnunet_gtk_select (void *cls,
789 * @param args leftover command line arguments (go to gtk) 802 * @param args leftover command line arguments (go to gtk)
790 * @param cfgfile name of the configuration file 803 * @param cfgfile name of the configuration file
791 * @param cfg handle to the configuration 804 * @param cfg handle to the configuration
792 */ 805 */
793static void 806static void
794run_main_loop (void *cls, 807run_main_loop (void *cls, char *const *args, const char *cfgfile,
795 char *const *args, 808 const struct GNUNET_CONFIGURATION_Handle *cfg)
796 const char *cfgfile,
797 const struct GNUNET_CONFIGURATION_Handle *cfg)
798{ 809{
799 struct GNUNET_GTK_MainLoop *ml = cls; 810 struct GNUNET_GTK_MainLoop *ml = cls;
800 int argc; 811 int argc;
801 812
802 /* command-line processing for Gtk arguments */ 813 /* command-line processing for Gtk arguments */
803 argc = 0; 814 argc = 0;
804 while (args[argc] != NULL) argc++; 815 while (args[argc] != NULL)
816 argc++;
805 gtk_init (&argc, (char ***) &args); 817 gtk_init (&argc, (char ***) &args);
806 818
807 /* setup main context */ 819 /* setup main context */
@@ -828,16 +840,16 @@ run_main_loop (void *cls,
828 840
829 /* run main task of the application */ 841 /* run main task of the application */
830 GNUNET_SCHEDULER_add_continuation (ml->main_task, ml, 842 GNUNET_SCHEDULER_add_continuation (ml->main_task, ml,
831 GNUNET_SCHEDULER_REASON_STARTUP); 843 GNUNET_SCHEDULER_REASON_STARTUP);
832 844
833 /* start the Gtk event loop */ 845 /* start the Gtk event loop */
834 GNUNET_assert (TRUE == g_main_context_acquire (ml->gmc)); 846 GNUNET_assert (TRUE == g_main_context_acquire (ml->gmc));
835 GNUNET_SCHEDULER_set_select (&gnunet_gtk_select, ml); 847 GNUNET_SCHEDULER_set_select (&gnunet_gtk_select, ml);
836 848
837 /* keep Gtk event loop running even if there are no GNUnet tasks */ 849 /* keep Gtk event loop running even if there are no GNUnet tasks */
838 ml->dummy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 850 ml->dummy_task =
839 &keepalive_task, 851 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
840 ml); 852 &keepalive_task, ml);
841 853
842} 854}
843 855
@@ -855,13 +867,11 @@ run_main_loop (void *cls,
855 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line options, etc) 867 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. bad command-line options, etc)
856 */ 868 */
857int 869int
858GNUNET_GTK_main_loop_start (const char *binary_name, 870GNUNET_GTK_main_loop_start (const char *binary_name, const char *binary_help,
859 const char *binary_help, 871 int argc, char *const *argv,
860 int argc, 872 struct GNUNET_GETOPT_CommandLineOption *options,
861 char *const*argv, 873 const char *main_window_file,
862 struct GNUNET_GETOPT_CommandLineOption *options, 874 GNUNET_SCHEDULER_Task main_task)
863 const char *main_window_file,
864 GNUNET_SCHEDULER_Task main_task)
865{ 875{
866 struct GNUNET_GTK_MainLoop ml; 876 struct GNUNET_GTK_MainLoop ml;
867 int ret; 877 int ret;
@@ -869,11 +879,9 @@ GNUNET_GTK_main_loop_start (const char *binary_name,
869 memset (&ml, 0, sizeof (ml)); 879 memset (&ml, 0, sizeof (ml));
870 ml.main_window_file = main_window_file; 880 ml.main_window_file = main_window_file;
871 ml.main_task = main_task; 881 ml.main_task = main_task;
872 ret = GNUNET_PROGRAM_run (argc, argv, 882 ret =
873 binary_name, 883 GNUNET_PROGRAM_run (argc, argv, binary_name, "GTK GUI for GNUnet",
874 "GTK GUI for GNUnet", 884 options, &run_main_loop, &ml);
875 options,
876 &run_main_loop, &ml);
877 if (NULL != ml.cached_poll_array) 885 if (NULL != ml.cached_poll_array)
878 g_free (ml.cached_poll_array); 886 g_free (ml.cached_poll_array);
879 if (NULL != ml.rs) 887 if (NULL != ml.rs)