+ GNUNET_CONTAINER_slist_add (handles_except,
+ GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+ fh,
+ sizeof (struct GNUNET_DISK_FileHandle));
+ }
+ }
+ }
+ }
+
+ sp.status = 0;
+
+ if (nfds > 0)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding the socket event to the array as %d\n", nhandles);
+ handle_array[nhandles++] = select_finished_event;
+ if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+ sp.tv = NULL;
+ else
+ {
+ select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
+ select_timeout.tv_usec = 1000 * (timeout.rel_value -
+ (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
+ sp.tv = &select_timeout;
+ }
+ FD_SET (select_wakeup_socket, &aread);
+ sp.r = &aread;
+ sp.w = &awrite;
+ sp.e = &aexcept;
+ /* Failed connections cause sockets to be set in errorfds on W32,
+ * but on POSIX it should set them in writefds.
+ * First copy all awrite sockets to aexcept, later we'll
+ * check aexcept and set its contents in awrite as well
+ * Sockets are also set in errorfds when OOB data is available,
+ * but we don't use OOB data.
+ */
+ for (i = 0; i < awrite.fd_count; i++)
+ FD_SET (awrite.fd_array[i], &aexcept);
+ ResetEvent (select_finished_event);
+ SetEvent (select_standby_event);
+ }
+
+ handle_array[nhandles] = NULL;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
+ nfds, nhandles, (unsigned long long) ms_total);
+ if (nhandles)
+ {
+ returncode =
+ WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
+ returncode);
+ }
+ else if (nfds > 0)
+ {
+ i = (int) WaitForSingleObject (select_finished_event, INFINITE);
+ returncode = WAIT_TIMEOUT;
+ }
+ else
+ {
+ /* Shouldn't come this far. If it does - investigate. */
+ GNUNET_assert (0);
+ }
+
+ if (nfds > 0)
+ {
+ /* Don't wake up select-thread when delay is 0, it should return immediately
+ * and wake up by itself.
+ */
+ if (ms_total != 0)
+ i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
+ i = (int) WaitForSingleObject (select_finished_event, INFINITE);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
+ if (ms_total != 0)
+ {
+ do
+ {
+ i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
+ } while (i == 1);
+ }
+ /* Check aexcept, add its contents to awrite */
+ for (i = 0; i < aexcept.fd_count; i++)
+ FD_SET (aexcept.fd_array[i], &awrite);
+ }
+
+ returnedpos = returncode - WAIT_OBJECT_0;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
+
+ if (nhandles && (returnedpos < nhandles))
+ {
+ DWORD waitstatus;
+
+ if (sp.status > 0)
+ retcode += sp.status;
+
+ if ((writePipePos != -1) && (returnedpos < writePipePos))
+ {
+ GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
+ retcode += write_handles;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
+ /* We have some pipes ready for read. */
+ if (returnedpos < readPipes)
+ {
+ for (i = 0; i < readPipes; i++)
+ {
+ DWORD error;
+ BOOL bret;
+
+ SetLastError (0);
+ waitstatus = 0;
+ bret =
+ PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
+ error = GetLastError ();
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
+ i, readArray[i]->h, bret, waitstatus, error);
+ if (bret == 0)
+ {
+ /* TODO: either add more errors to this condition, or eliminate it
+ * entirely (failed to peek -> pipe is in serious trouble, should
+ * be selected as readable).
+ */
+ if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
+ continue;
+ }
+ else if (waitstatus <= 0)
+ continue;
+ GNUNET_CONTAINER_slist_add (handles_read,
+ GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+ readArray[i],
+ sizeof (struct GNUNET_DISK_FileHandle));
+ retcode++;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
+ readArray[i], readArray[i]->h);
+ }
+ }
+ }
+ if (!nhandles || (returnedpos >= nhandles))
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
+ if (rfds)
+ {
+ struct GNUNET_CONTAINER_SList_Iterator t;
+
+ for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
+ GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
+ GNUNET_CONTAINER_slist_next (&t))
+ {
+ struct GNUNET_DISK_FileHandle *fh;
+
+ fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
+ NULL);
+ if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
+ {
+ CancelIo (fh->h);
+ }
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
+ GNUNET_NETWORK_fdset_zero (rfds);
+ if (retcode != -1 && nhandles && (returnedpos < nhandles))
+ GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
+ GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
+ }
+ if (wfds)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
+ GNUNET_NETWORK_fdset_zero (wfds);
+ if (retcode != -1 && nhandles && (returnedpos < nhandles))
+ GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
+ GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
+ }
+ if (efds)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
+ GNUNET_NETWORK_fdset_zero (efds);
+ if (retcode != -1 && nhandles && (returnedpos < nhandles))
+ GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
+ GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
+ }
+ GNUNET_CONTAINER_slist_destroy (handles_read);
+ GNUNET_CONTAINER_slist_destroy (handles_write);
+ GNUNET_CONTAINER_slist_destroy (handles_except);
+#if DEBUG_NETWORK
+ if (rfds)
+ {
+ struct GNUNET_CONTAINER_SList_Iterator t;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
+ for (i = 0; i < rfds->sds.fd_count; i++)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
+ }
+ for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
+ GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
+ GNUNET_CONTAINER_slist_next (&t))
+ {
+ struct GNUNET_DISK_FileHandle *fh;
+
+ fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
+ NULL);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
+ }
+ }
+ if (wfds)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
+ for (i = 0; i < wfds->sds.fd_count; i++)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
+ }
+ }
+ if (efds)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
+ for (i = 0; i < efds->sds.fd_count; i++)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
+ }
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
+#endif
+ if (nhandles && (returnedpos < nhandles))
+ return retcode;
+ else
+#endif
+ return 0;