Index: src/include/gnunet_os_lib.h
===================================================================
--- src/include/gnunet_os_lib.h	(revision 13625)
+++ src/include/gnunet_os_lib.h	(working copy)
@@ -273,6 +273,18 @@
  */
 int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc);
 
+/**
+ * Read env variable and set up the read end of the control
+ * pipe that parent uses to send signals to this process.
+ *
+ * Only does something on Windows
+ *
+ * @param cls user-specified parameter (NULL)
+ * @param tc task context
+ */
+void GNUNET_OS_install_parent_control_handler (void *cls,
+                                               const struct
+                                               GNUNET_SCHEDULER_TaskContext * tc);
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
Index: src/util/scheduler.c
===================================================================
--- src/util/scheduler.c	(revision 13625)
+++ src/util/scheduler.c	(working copy)
@@ -744,6 +744,7 @@
   shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown);
 #endif
   current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
+  GNUNET_SCHEDULER_add_continuation (GNUNET_OS_install_parent_control_handler, NULL, GNUNET_SCHEDULER_REASON_STARTUP);
   GNUNET_SCHEDULER_add_continuation (task,
                                      task_cls,
                                      GNUNET_SCHEDULER_REASON_STARTUP);
@@ -1351,8 +1352,7 @@
   GNUNET_assert (rfd != NULL);
   rs = GNUNET_NETWORK_fdset_create ();
   GNUNET_NETWORK_fdset_handle_set (rs, rfd);
-  ret = GNUNET_SCHEDULER_add_select (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_KEEP,
+  ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP,
                                      GNUNET_SCHEDULER_NO_TASK, delay,
                                      rs, NULL, task, task_cls);
   GNUNET_NETWORK_fdset_destroy (rs);
@@ -1400,8 +1400,7 @@
   GNUNET_assert (wfd != NULL);
   ws = GNUNET_NETWORK_fdset_create ();
   GNUNET_NETWORK_fdset_handle_set (ws, wfd);
-  ret = GNUNET_SCHEDULER_add_select (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_KEEP,
+  ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP,
                                      GNUNET_SCHEDULER_NO_TASK,
                                      delay, NULL, ws, task, task_cls);
   GNUNET_NETWORK_fdset_destroy (ws);
Index: src/util/os_priority.c
===================================================================
--- src/util/os_priority.c	(revision 13625)
+++ src/util/os_priority.c	(working copy)
@@ -29,28 +29,95 @@
 #include "gnunet_os_lib.h"
 #include "disk.h"
 
+#define GNUNET_OS_NT_CONTROL_PIPE "GNUNET_OS_NT_CONTROL_PIPE"
+
 struct GNUNET_OS_Process
 {
   pid_t pid;
 #if WINDOWS
   HANDLE handle;
+  struct GNUNET_DISK_PipeHandle *control_pipe;
 #endif
 };
 
 static struct GNUNET_OS_Process current_process;
 
-
 #if WINDOWS
-void
-GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle)
+void GNUNET_OS_parent_control_handler (void *cls,
+                                       const struct
+                                       GNUNET_SCHEDULER_TaskContext * tc)
 {
-  if (proc->handle != NULL)
-    CloseHandle (proc->handle);
-  proc->handle = handle;
+  struct GNUNET_DISK_PipeHandle *control_pipe = (struct GNUNET_DISK_PipeHandle *) cls;
+  unsigned char code;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_OS_parent_control_handler is invoked because of %d\n", tc->reason);
+
+  if (tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | GNUNET_SCHEDULER_REASON_PREREQ_DONE))
+  {
+      GNUNET_DISK_pipe_close (control_pipe);
+  }
+  else
+  {
+    if (GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &code, sizeof (char)) != sizeof (char))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_DISK_file_read have failed, errno = %d. Closing the control pipe.\n", errno);
+      GNUNET_DISK_pipe_close (control_pipe);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d\n", code);
+      switch (code)
+      {
+        case 0:
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Raising SIGTERM\n");
+          raise (SIGTERM);
+          break;
+        case 1:
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Raising SIGKILL\n");
+          raise (SIGKILL);
+          break;
+        case 255:
+          /* read more bytes - a possibility for extended signals
+           * in case 254 different valies is not enough
+           */
+          break;
+        default:
+          break;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-adding parent control handler pipe to the scheduler\n");
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), GNUNET_OS_parent_control_handler, control_pipe);
+    }
+  }
 }
 #endif
 
+void
+GNUNET_OS_install_parent_control_handler (void *cls,
+                                          const struct
+                                          GNUNET_SCHEDULER_TaskContext * tc)
+{
+#ifdef WINDOWS
+  char *env_buf;
+  char *endptr;
+  HANDLE control_pipe_end[2];
+  struct GNUNET_DISK_PipeHandle *control_pipe = NULL;
 
+  env_buf = getenv (GNUNET_OS_NT_CONTROL_PIPE);
+  if (env_buf == NULL || strlen (env_buf) <= 0 || env_buf[0] < '0' || env_buf[0] > '9')
+    return;
+
+  control_pipe_end[0] = (HANDLE) strtol (env_buf, &endptr, 10);
+  control_pipe_end[1] = INVALID_HANDLE_VALUE;
+ 
+  control_pipe = GNUNET_DISK_pipe_from_internal_handles_ (GNUNET_NO, &control_pipe_end[0], &control_pipe_end[1], sizeof (HANDLE));
+  if (control_pipe == NULL)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe to the scheduler\n");
+  GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), GNUNET_OS_parent_control_handler, control_pipe);
+#endif
+}
+
 /**
  * Get process structure for current process
  *
@@ -66,7 +133,7 @@
   current_process.pid = GetCurrentProcessId ();
   current_process.handle = GetCurrentProcess ();
 #else
-  current_process.pid = 0;
+  current_process.pid = getpid ();
 #endif
   return &current_process;
 }
@@ -75,27 +142,49 @@
 GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
 {
 #if WINDOWS
-  if (sig == SIGKILL || sig == SIGTERM)
+  unsigned char c;
+  DWORD dwresult, error_code = NO_ERROR;
+  BOOL bresult = 1;
+
+  switch (sig)
   {
-    HANDLE h = proc->handle;
-    if (NULL == h)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-		  _("Invalid process information {%d, %08X}\n"),
-		  proc->pid,
-		  h);
+    case SIGKILL:
+      c = 1;
+      break;
+    case SIGTERM:
+      c = 0;
+      break;
+    default:
+      errno = EINVAL;
       return -1;
-    }
-    if (!TerminateProcess (h, 0))
+  }
+
+  if (GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (proc->control_pipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c)) != sizeof (c))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to write into control pipe, errno is %d\n", errno);
+    bresult = 0;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote control code into control pipe, now waiting\n");
+    SetLastError (0);
+    dwresult = WaitForSingleObject (proc->handle, 4*1000);
+    error_code = GetLastError ();
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Woke up, returned %d, GLE is %d\n", dwresult, error_code);
+    if (WAIT_OBJECT_0 != dwresult || error_code != NO_ERROR)
     {
-      SetErrnoFromWinError (GetLastError ());
-      return -1;
+      SetLastError (0);
+      bresult = TerminateProcess (proc->handle, 0);
+      error_code = GetLastError ();
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TerminateProcess for the child returned %d, GLE is %d\n", bresult, error_code);
     }
-    else
-      return 0;
   }
-  errno = EINVAL;
-  return -1;
+  if (error_code != NO_ERROR || !bresult)
+  {
+    return -1;
+  }
+  else
+    return 0;
 #else
   return kill (proc->pid, sig);
 #endif
@@ -130,15 +219,10 @@
 extern GNUNET_SIGNAL_Handler w32_sigchld_handler;
 
 /**
- * Make seaspider happy.
- */
-#define DWORD_WINAPI DWORD WINAPI
-
-/**
  * @brief Waits for a process to terminate and invokes the SIGCHLD handler
  * @param proc pointer to process structure
  */
-static DWORD_WINAPI
+static DWORD WINAPI
 ChildWaitThread (void *arg)
 {
   struct GNUNET_OS_Process *proc = (struct GNUNET_OS_Process *) arg;
@@ -368,19 +452,32 @@
   STARTUPINFO start;
   PROCESS_INFORMATION proc;
   struct GNUNET_OS_Process *gnunet_proc = NULL;
+  struct GNUNET_DISK_PipeHandle *control_pipe = NULL;
+  char *env_buf;
 
   HANDLE stdin_handle;
   HANDLE stdout_handle;
+  HANDLE control_pipe_read_end, control_pipe_write_end;
 
   char path[MAX_PATH + 1];
 
-  cmdlen = 0;
+  if ((HINSTANCE) 32 >= FindExecutableA (filename, NULL, path)) 
+    {
+      SetErrnoFromWinError (GetLastError ());
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename);
+      return NULL;
+    }
+
+  cmdlen = strlen (path) + 3;
   va_start (ap, filename);
   while (NULL != (arg = va_arg (ap, char *)))
+  {
       cmdlen = cmdlen + strlen (arg) + 3;
+  }
   va_end (ap);
 
   cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1));
+  idx += sprintf (idx, "\"%s\" ", path);
   va_start (ap, filename);
   while (NULL != (arg = va_arg (ap, char *)))
       idx += sprintf (idx, "\"%s\" ", arg);
@@ -404,30 +501,42 @@
       start.hStdOutput = stdout_handle;
     }
 
-  if (32 >= (int) FindExecutableA (filename, NULL, path)) 
-    {
-      SetErrnoFromWinError (GetLastError ());
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename);
-      return NULL;
-    }
+  control_pipe = GNUNET_DISK_pipe (GNUNET_NO, 1, 0);
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE));
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE));
 
+  GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end);
+  putenv (env_buf);
+  GNUNET_free (env_buf);
+
   if (!CreateProcessA
       (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start,
        &proc))
     {
       SetErrnoFromWinError (GetLastError ());
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path);
-      return NULL;
+      goto end;
     }
 
   gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
   gnunet_proc->pid = proc.dwProcessId;
   gnunet_proc->handle = proc.hProcess;
+  gnunet_proc->control_pipe = control_pipe;
 
   CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
 
   CloseHandle (proc.hThread);
+end:
 
+  GNUNET_asprintf (&env_buf, "%s=", GNUNET_OS_NT_CONTROL_PIPE);
+  putenv (env_buf);
+  GNUNET_free (env_buf);
+
+  if (gnunet_proc == NULL)
+    GNUNET_DISK_pipe_close (control_pipe);
+  else
+    GNUNET_DISK_pipe_close_end (control_pipe, GNUNET_DISK_PIPE_END_READ);
+
   GNUNET_free (cmd);
 
   return gnunet_proc;
@@ -557,10 +666,13 @@
   int argcount = 0;
   char non_const_filename[MAX_PATH +1];
   struct GNUNET_OS_Process *gnunet_proc = NULL;
+  struct GNUNET_DISK_PipeHandle *control_pipe = NULL;
+  char *env_buf;
+  HANDLE control_pipe_read_end, control_pipe_write_end;
 
   GNUNET_assert (lsocks == NULL);
 
-  if (32 >= (int) FindExecutableA (filename, NULL, non_const_filename)) 
+  if ((HINSTANCE) 32 >= FindExecutableA (filename, NULL, non_const_filename)) 
     {
       SetErrnoFromWinError (GetLastError ());
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename);
@@ -583,7 +695,12 @@
   arg = (char **) argv;
   while (*arg)
     {
-      non_const_argv[argcount] = GNUNET_strdup (*arg);
+      if (argcount == 0)
+        /* Otherwise we'll get the argv[0] without .exe extension,
+           that will break libtool wrapper */
+        non_const_argv[argcount] = GNUNET_strdup (non_const_filename);
+      else
+        non_const_argv[argcount] = GNUNET_strdup (*arg);
       arg++;
       argcount++;
     }
@@ -610,22 +727,43 @@
   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
 
-  if (!CreateProcess
-      (non_const_filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start,
+  control_pipe = GNUNET_DISK_pipe (GNUNET_NO, 1, 0);
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE));
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE));
+
+
+  GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end);
+  putenv (env_buf);
+  GNUNET_free (env_buf);
+
+  if (!CreateProcessA
+      (non_const_filename, cmd, NULL, NULL, TRUE,
+       DETACHED_PROCESS, NULL, NULL, &start,
        &proc))
     {
       SetErrnoFromWinError (GetLastError ());
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess");
-      return NULL;
+      goto end;
     }
 
   gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
   gnunet_proc->pid = proc.dwProcessId;
   gnunet_proc->handle = proc.hProcess;
+  gnunet_proc->control_pipe = control_pipe;
 
   CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
 
   CloseHandle (proc.hThread);
+end:
+  GNUNET_asprintf (&env_buf, "%s=", GNUNET_OS_NT_CONTROL_PIPE);
+  putenv (env_buf);
+  GNUNET_free (env_buf);
+
+  if (gnunet_proc == NULL)
+    GNUNET_DISK_pipe_close (control_pipe);
+  else
+    GNUNET_DISK_pipe_close_end (control_pipe, GNUNET_DISK_PIPE_END_READ);
+
   GNUNET_free (cmd);
 
   while (argcount > 0)
Index: src/util/network.c
===================================================================
--- src/util/network.c	(revision 13625)
+++ src/util/network.c	(working copy)
@@ -470,8 +470,8 @@
 
 #ifdef MSG_DONTWAIT
   flags |= MSG_DONTWAIT;
+#endif
 
-#endif
   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
@@ -1138,9 +1138,19 @@
 
             {
               HANDLE h;
-              DWORD dwBytes;
+              DWORD dwBytes = 0, error_code;
+              BOOL bresult;
               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
-              if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
+              bresult = PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL);
+              error_code = GetLastError ();
+              /* FIXME: This should fail when the pipe is _really_ invalid,
+               * should skip the pipe if the error means that it's
+               * temporarily unavailable, and should succeed if the pipe
+               * is broken (or that the otherwise valid pipe is in a condition
+               * that prevents further reading). 
+               * For now it succeeds only when the pipe is broken or readable.
+               */
+              if (!bresult && error_code != ERROR_BROKEN_PIPE)
                 {
                   retcode = -1;
                   SetErrnoFromWinError (GetLastError ());
@@ -1152,7 +1162,7 @@
 #endif
                   goto select_loop_end;
                 }
-              else if (dwBytes)
+              else if (dwBytes || error_code == ERROR_BROKEN_PIPE)
 
                 {
                   GNUNET_CONTAINER_slist_add (handles_read,
Index: src/util/disk.c
===================================================================
--- src/util/disk.c	(revision 13625)
+++ src/util/disk.c	(working copy)
@@ -1910,4 +1910,95 @@
   return GNUNET_OK;
 }
 
+struct GNUNET_DISK_FileHandle
+GNUNET_DISK_file_from_internal_handle_ (void *src, size_t src_len)
+{
+  struct GNUNET_DISK_FileHandle ret;
+#ifdef MINGW
+  if (src_len == sizeof (HANDLE))
+    ret.h = *(HANDLE *) src;
+  else
+    ret.h = INVALID_HANDLE_VALUE;
+#else
+  if (src_len == sizeof (int))
+    ret.fd = *(int *) src;
+  else
+    ret.fd = -1;
+#endif
+  return ret;
+}
+
+struct GNUNET_DISK_PipeHandle *
+GNUNET_DISK_pipe_from_internal_handles_ (int blocking, void *src0, void *src1, size_t src_len)
+{
+  struct GNUNET_DISK_PipeHandle *p;
+  struct GNUNET_DISK_FileHandle *fds;
+
+  p =
+    GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle) +
+                   2 * sizeof (struct GNUNET_DISK_FileHandle));
+  fds = (struct GNUNET_DISK_FileHandle *) &p[1];
+  p->fd[0] = &fds[0];
+  p->fd[1] = &fds[1];
+  fds[0] = GNUNET_DISK_file_from_internal_handle_ (src0, src_len);
+  fds[1] = GNUNET_DISK_file_from_internal_handle_ (src1, src_len);
+#ifndef MINGW
+  int fd[2];
+  int ret;
+  int flags;
+  int eno;
+
+  fd[0] = fds[0].fd;
+  fd[1] = fds[1].fd;
+  ret = 0;
+  if (fd[0] >= 0)
+  {
+    flags = fcntl (fd[0], F_GETFL);
+    if (!blocking)
+      flags |= O_NONBLOCK;
+    if (0 > fcntl (fd[0], F_SETFL, flags))
+      ret = -1;
+    flags = fcntl (fd[0], F_GETFD);
+    flags |= FD_CLOEXEC;
+    if (0 > fcntl (fd[0], F_SETFD, flags))
+      ret = -1;
+  }
+  if (fd[1] >= 0)
+  {
+    flags = fcntl (fd[1], F_GETFL);
+    if (!blocking)
+      flags |= O_NONBLOCK;
+    if (0 > fcntl (fd[1], F_SETFL, flags))
+      ret = -1;
+    flags = fcntl (fd[1], F_GETFD);
+    flags |= FD_CLOEXEC;
+    if (0 > fcntl (fd[1], F_SETFD, flags))
+      ret = -1;
+  }
+  if (ret == -1)
+    {
+      eno = errno;
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fcntl");
+      GNUNET_free (p);
+      errno = eno;
+      return NULL;    
+    }
+#else
+  /* Empirical fact: DuplicateHandle() on a handle inherited from the parent
+   * dies with ERROR_INVALID_HANDLE, so we won't try to duplicate these to
+   * make them inheritable/uninheritable.
+   */
+  if (!blocking)
+  {
+    DWORD mode;
+
+    mode = PIPE_NOWAIT;
+    SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL);
+    SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL);
+    /* this always fails on Windows 95, so we don't care about error handling */
+  }
+#endif
+  return p;
+}
+
 /* end of disk.c */
Index: src/util/disk.h
===================================================================
--- src/util/disk.h	(revision 13625)
+++ src/util/disk.h	(working copy)
@@ -72,4 +72,8 @@
 size_t dst_len);
  
+struct GNUNET_DISK_PipeHandle *GNUNET_DISK_pipe_from_internal_handles_ (int blocking, void *src0, void *src1, size_t src_len);+
++
 #endif  /* GNUNET_DISK_H_ */
