diff options
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | src/include/gnunet_disk_lib.h | 15 | ||||
-rw-r--r-- | src/include/gnunet_os_lib.h | 8 | ||||
-rw-r--r-- | src/util/disk.c | 133 | ||||
-rw-r--r-- | src/util/network.c | 21 | ||||
-rw-r--r-- | src/util/os_priority.c | 506 | ||||
-rw-r--r-- | src/util/scheduler.c | 5 |
7 files changed, 635 insertions, 70 deletions
diff --git a/configure.ac b/configure.ac index 8c747d283..6f6e47ea4 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -755,6 +755,23 @@ AC_MSG_RESULT($enable_malicious) | |||
755 | AM_CONDITIONAL([HAVE_MALICIOUS], [test "x$enable_malicious" = "x1"]) | 755 | AM_CONDITIONAL([HAVE_MALICIOUS], [test "x$enable_malicious" = "x1"]) |
756 | AC_DEFINE_UNQUOTED([HAVE_MALICIOUS], $enable_malicious, [Compile malicious code]) | 756 | AC_DEFINE_UNQUOTED([HAVE_MALICIOUS], $enable_malicious, [Compile malicious code]) |
757 | 757 | ||
758 | # should code be enabled that works around missing OS functionality on Windows? | ||
759 | # used for test cases | ||
760 | AC_ARG_ENABLE(windows_workarounds, [AS_HELP_STRING([--enable-windows_workarounds], | ||
761 | [enable workarounds used on Windows (only useful for test cases)])]) | ||
762 | if test $build_target = "mingw" | ||
763 | then | ||
764 | workarounds=1 | ||
765 | else | ||
766 | if test x$enable_windows_workarounds = "xyes" | ||
767 | then | ||
768 | workarounds=1 | ||
769 | else | ||
770 | workarounds=0 | ||
771 | fi | ||
772 | fi | ||
773 | AC_DEFINE_UNQUOTED([ENABLE_WINDOWS_WORKAROUNDS], $workarounds, [enable workarounds used on Windows (only useful for test cases)]) | ||
774 | |||
758 | # gcov compilation | 775 | # gcov compilation |
759 | use_gcov=no | 776 | use_gcov=no |
760 | AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage], | 777 | AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage], |
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h index a59d10ed0..383a9daa2 100644 --- a/src/include/gnunet_disk_lib.h +++ b/src/include/gnunet_disk_lib.h | |||
@@ -643,8 +643,19 @@ int GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h); | |||
643 | int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h); | 643 | int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h); |
644 | 644 | ||
645 | /** | 645 | /** |
646 | * Creates a named pipe/FIFO | 646 | * Creates a named pipe/FIFO and opens it |
647 | * @param fn name of the named pipe | 647 | * @param fn pointer to the name of the named pipe or to NULL |
648 | * @param flags open flags | ||
649 | * @param perm access permissions | ||
650 | * @return pipe handle on success, NULL on error | ||
651 | */ | ||
652 | struct GNUNET_DISK_FileHandle *GNUNET_DISK_npipe_create (char **fn, | ||
653 | enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm); | ||
654 | |||
655 | /** | ||
656 | * Opens already existing named pipe/FIFO | ||
657 | * | ||
658 | * @param fn name of an existing named pipe | ||
648 | * @param flags open flags | 659 | * @param flags open flags |
649 | * @param perm access permissions | 660 | * @param perm access permissions |
650 | * @return pipe handle on success, NULL on error | 661 | * @return pipe handle on success, NULL on error |
diff --git a/src/include/gnunet_os_lib.h b/src/include/gnunet_os_lib.h index 5326e20cf..7bd65adcb 100644 --- a/src/include/gnunet_os_lib.h +++ b/src/include/gnunet_os_lib.h | |||
@@ -274,6 +274,14 @@ int GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, | |||
274 | int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc); | 274 | int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc); |
275 | 275 | ||
276 | 276 | ||
277 | /** | ||
278 | * Connects this process to its parent via pipe | ||
279 | */ | ||
280 | void | ||
281 | GNUNET_OS_install_parent_control_handler (void *cls, | ||
282 | const struct | ||
283 | GNUNET_SCHEDULER_TaskContext * tc); | ||
284 | |||
277 | #if 0 /* keep Emacsens' auto-indent happy */ | 285 | #if 0 /* keep Emacsens' auto-indent happy */ |
278 | { | 286 | { |
279 | #endif | 287 | #endif |
diff --git a/src/util/disk.c b/src/util/disk.c index bb7929551..3c9469ca7 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -31,8 +31,10 @@ | |||
31 | #include "gnunet_disk_lib.h" | 31 | #include "gnunet_disk_lib.h" |
32 | #include "gnunet_scheduler_lib.h" | 32 | #include "gnunet_scheduler_lib.h" |
33 | #include "gnunet_strings_lib.h" | 33 | #include "gnunet_strings_lib.h" |
34 | #include "gnunet_crypto_lib.h" | ||
34 | #include "disk.h" | 35 | #include "disk.h" |
35 | 36 | ||
37 | #define DEBUG_NPIPE GNUNET_YES | ||
36 | 38 | ||
37 | /** | 39 | /** |
38 | * Block size for IO for copying files. | 40 | * Block size for IO for copying files. |
@@ -1876,20 +1878,20 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p) | |||
1876 | 1878 | ||
1877 | 1879 | ||
1878 | /** | 1880 | /** |
1879 | * Creates a named pipe/FIFO | 1881 | * Creates a named pipe/FIFO and opens it |
1880 | * @param fn name of the named pipe | 1882 | * @param fn pointer to the name of the named pipe or to NULL |
1881 | * @param flags open flags | 1883 | * @param flags open flags |
1882 | * @param perm access permissions | 1884 | * @param perm access permissions |
1883 | * @return pipe handle on success, NULL on error | 1885 | * @return pipe handle on success, NULL on error |
1884 | */ | 1886 | */ |
1885 | struct GNUNET_DISK_FileHandle * | 1887 | struct GNUNET_DISK_FileHandle * |
1886 | GNUNET_DISK_npipe_open (const char *fn, | 1888 | GNUNET_DISK_npipe_create (char **fn, |
1887 | enum GNUNET_DISK_OpenFlags flags, | 1889 | enum GNUNET_DISK_OpenFlags flags, |
1888 | enum GNUNET_DISK_AccessPermissions perm) | 1890 | enum GNUNET_DISK_AccessPermissions perm) |
1889 | { | 1891 | { |
1890 | #ifdef MINGW | 1892 | #ifdef MINGW |
1891 | struct GNUNET_DISK_FileHandle *ret; | 1893 | struct GNUNET_DISK_FileHandle *ret; |
1892 | HANDLE h; | 1894 | HANDLE h = NULL; |
1893 | DWORD openMode; | 1895 | DWORD openMode; |
1894 | char *name; | 1896 | char *name; |
1895 | 1897 | ||
@@ -1904,22 +1906,80 @@ GNUNET_DISK_npipe_open (const char *fn, | |||
1904 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) | 1906 | if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) |
1905 | openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; | 1907 | openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; |
1906 | 1908 | ||
1907 | GNUNET_asprintf(&name, "\\\\.\\pipe\\pipename\\%s", fn); | 1909 | while (h == NULL) |
1908 | h = CreateNamedPipe (fn, openMode | FILE_FLAG_OVERLAPPED, | ||
1909 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL); | ||
1910 | GNUNET_free(name); | ||
1911 | if (h == NULL) | ||
1912 | { | 1910 | { |
1913 | SetErrnoFromWinError(GetLastError()); | 1911 | DWORD error_code; |
1914 | return NULL; | 1912 | name = NULL; |
1913 | if (*fn != NULL) | ||
1914 | { | ||
1915 | GNUNET_asprintf(&name, "\\\\.\\pipe\\%.246s", fn); | ||
1916 | #if DEBUG_NPIPE | ||
1917 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to create an instance of named pipe `%s'\n", name); | ||
1918 | #endif | ||
1919 | h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED, | ||
1920 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL); | ||
1921 | } | ||
1922 | else | ||
1923 | { | ||
1924 | GNUNET_asprintf(fn, "\\\\.\\pipe\\gnunet-%llu", | ||
1925 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX)); | ||
1926 | #if DEBUG_NPIPE | ||
1927 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n", *fn); | ||
1928 | #endif | ||
1929 | h = CreateNamedPipe (*fn, openMode | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, | ||
1930 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL); | ||
1931 | } | ||
1932 | error_code = GetLastError (); | ||
1933 | if (name) | ||
1934 | GNUNET_free(name); | ||
1935 | /* don't re-set name to NULL yet */ | ||
1936 | if (h == INVALID_HANDLE_VALUE) | ||
1937 | { | ||
1938 | SetErrnoFromWinError(error_code); | ||
1939 | #if DEBUG_NPIPE | ||
1940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe creation have failed because of %d, errno is %d\n", error_code, errno); | ||
1941 | #endif | ||
1942 | if (name == NULL) | ||
1943 | { | ||
1944 | #if DEBUG_NPIPE | ||
1945 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe was to be unique, considering re-creation\n"); | ||
1946 | #endif | ||
1947 | GNUNET_free (*fn); | ||
1948 | *fn = NULL; | ||
1949 | if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY) | ||
1950 | { | ||
1951 | return NULL; | ||
1952 | } | ||
1953 | #if DEBUG_NPIPE | ||
1954 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pipe name was not unique, trying again\n"); | ||
1955 | #endif | ||
1956 | h = NULL; | ||
1957 | } | ||
1958 | else | ||
1959 | return NULL; | ||
1960 | } | ||
1915 | } | 1961 | } |
1962 | errno = 0; | ||
1916 | 1963 | ||
1917 | ret = GNUNET_malloc(sizeof(*ret)); | 1964 | ret = GNUNET_malloc(sizeof(*ret)); |
1918 | ret->h = h; | 1965 | ret->h = h; |
1966 | ret->type = GNUNET_PIPE; | ||
1919 | 1967 | ||
1920 | return ret; | 1968 | return ret; |
1921 | #else | 1969 | #else |
1922 | if (mkfifo(fn, translate_unix_perms(perm)) == -1) | 1970 | if (*fn == NULL) |
1971 | { | ||
1972 | char dir[] = "/tmp/gnunet-pipe-XXXXXX"; | ||
1973 | |||
1974 | if (mkdtemp(dir) == NULL) | ||
1975 | { | ||
1976 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "mkdtemp"); | ||
1977 | return NULL; | ||
1978 | } | ||
1979 | GNUNET_asprintf(fn, "%s/child-control", dir); | ||
1980 | } | ||
1981 | |||
1982 | if (mkfifo(*fn, translate_unix_perms(perm)) == -1) | ||
1923 | { | 1983 | { |
1924 | if ( (errno != EEXIST) || | 1984 | if ( (errno != EEXIST) || |
1925 | (0 != (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) ) | 1985 | (0 != (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) ) |
@@ -1932,6 +1992,51 @@ GNUNET_DISK_npipe_open (const char *fn, | |||
1932 | } | 1992 | } |
1933 | 1993 | ||
1934 | /** | 1994 | /** |
1995 | * Opens already existing named pipe/FIFO | ||
1996 | * | ||
1997 | * @param fn name of an existing named pipe | ||
1998 | * @param flags open flags | ||
1999 | * @param perm access permissions | ||
2000 | * @return pipe handle on success, NULL on error | ||
2001 | */ | ||
2002 | struct GNUNET_DISK_FileHandle * | ||
2003 | GNUNET_DISK_npipe_open (const char *fn, | ||
2004 | enum GNUNET_DISK_OpenFlags flags, | ||
2005 | enum GNUNET_DISK_AccessPermissions perm) | ||
2006 | { | ||
2007 | #ifdef MINGW | ||
2008 | struct GNUNET_DISK_FileHandle *ret; | ||
2009 | HANDLE h; | ||
2010 | DWORD openMode; | ||
2011 | |||
2012 | openMode = 0; | ||
2013 | if (flags & GNUNET_DISK_OPEN_READWRITE) | ||
2014 | openMode = GENERIC_WRITE | GENERIC_READ; | ||
2015 | else if (flags & GNUNET_DISK_OPEN_READ) | ||
2016 | openMode = GENERIC_READ; | ||
2017 | else if (flags & GNUNET_DISK_OPEN_WRITE) | ||
2018 | openMode = GENERIC_WRITE; | ||
2019 | |||
2020 | h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING, | ||
2021 | FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL); | ||
2022 | if (h == INVALID_HANDLE_VALUE) | ||
2023 | { | ||
2024 | SetErrnoFromWinError(GetLastError()); | ||
2025 | return NULL; | ||
2026 | } | ||
2027 | |||
2028 | ret = GNUNET_malloc(sizeof(*ret)); | ||
2029 | ret->h = h; | ||
2030 | ret->type = GNUNET_PIPE; | ||
2031 | |||
2032 | return ret; | ||
2033 | #else | ||
2034 | flags = flags & (~GNUNET_DISK_OPEN_FAILIFEXISTS); | ||
2035 | return GNUNET_DISK_file_open(fn, flags, perm); | ||
2036 | #endif | ||
2037 | } | ||
2038 | |||
2039 | /** | ||
1935 | * Closes a named pipe/FIFO | 2040 | * Closes a named pipe/FIFO |
1936 | * @param pipe named pipe | 2041 | * @param pipe named pipe |
1937 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | 2042 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise |
diff --git a/src/util/network.c b/src/util/network.c index 08121928d..9e85a3be9 100644 --- a/src/util/network.c +++ b/src/util/network.c | |||
@@ -1127,15 +1127,26 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | |||
1127 | { | 1127 | { |
1128 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) | 1128 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) |
1129 | { | 1129 | { |
1130 | retcode = -1; | 1130 | DWORD error_code = GetLastError (); |
1131 | SetErrnoFromWinError (GetLastError ()); | 1131 | switch (error_code) |
1132 | { | ||
1133 | case ERROR_BROKEN_PIPE: | ||
1134 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1135 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1136 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1137 | retcode++; | ||
1138 | break; | ||
1139 | default: | ||
1140 | retcode = -1; | ||
1141 | SetErrnoFromWinError (error_code); | ||
1132 | 1142 | ||
1133 | #if DEBUG_NETWORK | 1143 | #if DEBUG_NETWORK |
1134 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | 1144 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, |
1135 | "PeekNamedPipe"); | 1145 | "PeekNamedPipe"); |
1136 | 1146 | ||
1137 | #endif | 1147 | #endif |
1138 | goto select_loop_end; | 1148 | goto select_loop_end; |
1149 | } | ||
1139 | } | 1150 | } |
1140 | else if (dwBytes) | 1151 | else if (dwBytes) |
1141 | 1152 | ||
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index fb6c2922c..e9ca9deea 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -27,29 +27,87 @@ | |||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include "gnunet_common.h" | 28 | #include "gnunet_common.h" |
29 | #include "gnunet_os_lib.h" | 29 | #include "gnunet_os_lib.h" |
30 | #include "gnunet_scheduler_lib.h" | ||
30 | #include "disk.h" | 31 | #include "disk.h" |
31 | 32 | ||
33 | #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" | ||
34 | |||
32 | struct GNUNET_OS_Process | 35 | struct GNUNET_OS_Process |
33 | { | 36 | { |
34 | pid_t pid; | 37 | pid_t pid; |
35 | #if WINDOWS | 38 | #if WINDOWS |
36 | HANDLE handle; | 39 | HANDLE handle; |
37 | #endif | 40 | #endif |
41 | int sig; | ||
42 | struct GNUNET_DISK_FileHandle *control_pipe; | ||
38 | }; | 43 | }; |
39 | 44 | ||
40 | static struct GNUNET_OS_Process current_process; | 45 | static struct GNUNET_OS_Process current_process; |
41 | 46 | ||
42 | 47 | ||
43 | #if WINDOWS | 48 | /** |
49 | * This handler is called when there are control data to be read on the pipe | ||
50 | */ | ||
44 | void | 51 | void |
45 | GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle) | 52 | GNUNET_OS_parent_control_handler (void *cls, |
53 | const struct | ||
54 | GNUNET_SCHEDULER_TaskContext * tc) | ||
46 | { | 55 | { |
47 | if (proc->handle != NULL) | 56 | struct GNUNET_DISK_FileHandle *control_pipe = (struct GNUNET_DISK_FileHandle *) cls; |
48 | CloseHandle (proc->handle); | 57 | int sig; |
49 | proc->handle = handle; | 58 | |
59 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, tc->reason); | ||
60 | |||
61 | if (tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | GNUNET_SCHEDULER_REASON_PREREQ_DONE)) | ||
62 | { | ||
63 | GNUNET_DISK_npipe_close (control_pipe); | ||
64 | } | ||
65 | else | ||
66 | { | ||
67 | if (GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig)) != sizeof (sig)) | ||
68 | { | ||
69 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); | ||
70 | GNUNET_DISK_npipe_close (control_pipe); | ||
71 | } | ||
72 | else | ||
73 | { | ||
74 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent\n", sig); | ||
75 | raise (sig); | ||
76 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-scheduling the parent control handler pipe\n"); | ||
77 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, GNUNET_OS_parent_control_handler, control_pipe); | ||
78 | } | ||
79 | } | ||
50 | } | 80 | } |
51 | #endif | ||
52 | 81 | ||
82 | /** | ||
83 | * Connects this process to its parent via pipe | ||
84 | */ | ||
85 | void | ||
86 | GNUNET_OS_install_parent_control_handler (void *cls, | ||
87 | const struct | ||
88 | GNUNET_SCHEDULER_TaskContext * tc) | ||
89 | { | ||
90 | char *env_buf; | ||
91 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
92 | |||
93 | env_buf = getenv (GNUNET_OS_CONTROL_PIPE); | ||
94 | if (env_buf == NULL || strlen (env_buf) <= 0) | ||
95 | { | ||
96 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not installing a handler because %s=%s\n", GNUNET_OS_CONTROL_PIPE, env_buf); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | control_pipe = GNUNET_DISK_npipe_open (env_buf, GNUNET_DISK_OPEN_READ, | ||
101 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); | ||
102 | if (control_pipe == NULL) | ||
103 | { | ||
104 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to open the pipe `%s'\n", env_buf); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); | ||
109 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, GNUNET_OS_parent_control_handler, control_pipe); | ||
110 | } | ||
53 | 111 | ||
54 | /** | 112 | /** |
55 | * Get process structure for current process | 113 | * Get process structure for current process |
@@ -74,28 +132,60 @@ GNUNET_OS_process_current () | |||
74 | int | 132 | int |
75 | GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) | 133 | GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) |
76 | { | 134 | { |
77 | #if WINDOWS | 135 | #if ENABLE_WINDOWS_WORKAROUNDS |
78 | if (sig == SIGKILL || sig == SIGTERM) | 136 | int res; |
137 | int ret; | ||
138 | |||
139 | ret = GNUNET_DISK_file_write (proc->control_pipe, &sig, sizeof(sig)); | ||
140 | if (ret != sizeof(sig)) | ||
79 | { | 141 | { |
80 | HANDLE h = proc->handle; | 142 | if (errno == ECOMM) |
81 | if (NULL == h) | 143 | /* Child process is not controllable via pipe */ |
82 | { | 144 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
83 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 145 | "Child process is not controllable, will kill it directly\n"); |
84 | _("Invalid process information {%d, %08X}\n"), | ||
85 | proc->pid, | ||
86 | h); | ||
87 | return -1; | ||
88 | } | ||
89 | if (!TerminateProcess (h, 0)) | ||
90 | { | ||
91 | SetErrnoFromWinError (GetLastError ()); | ||
92 | return -1; | ||
93 | } | ||
94 | else | 146 | else |
95 | return 0; | 147 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
148 | "Failed to write into control pipe , errno is %d\n", errno); | ||
149 | res = PLIBC_KILL (proc->pid, sig); | ||
96 | } | 150 | } |
97 | errno = EINVAL; | 151 | else |
98 | return -1; | 152 | { |
153 | struct GNUNET_NETWORK_FDSet *rfds; | ||
154 | struct GNUNET_NETWORK_FDSet *efds; | ||
155 | |||
156 | rfds = GNUNET_NETWORK_fdset_create (); | ||
157 | efds = GNUNET_NETWORK_fdset_create (); | ||
158 | |||
159 | GNUNET_NETWORK_fdset_handle_set (rfds, proc->control_pipe); | ||
160 | GNUNET_NETWORK_fdset_handle_set (efds, proc->control_pipe); | ||
161 | |||
162 | read_next: | ||
163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
164 | "Wrote control code into control pipe, now waiting\n"); | ||
165 | |||
166 | ret = GNUNET_NETWORK_socket_select (rfds, NULL, efds, | ||
167 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_unit (), | ||
168 | 5000)); | ||
169 | |||
170 | if (ret < 1 || GNUNET_NETWORK_fdset_handle_isset (efds, | ||
171 | proc->control_pipe)) | ||
172 | { | ||
173 | /* Just to be sure */ | ||
174 | PLIBC_KILL (proc->pid, sig); | ||
175 | res = 0; | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | if (GNUNET_DISK_file_read (proc->control_pipe, &ret, | ||
180 | sizeof(ret)) != GNUNET_OK) | ||
181 | res = PLIBC_KILL (proc->pid, sig); | ||
182 | |||
183 | /* Child signaled shutdown is in progress */ | ||
184 | goto read_next; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return res; | ||
99 | #else | 189 | #else |
100 | return kill (proc->pid, sig); | 190 | return kill (proc->pid, sig); |
101 | #endif | 191 | #endif |
@@ -117,13 +207,19 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc) | |||
117 | void | 207 | void |
118 | GNUNET_OS_process_close (struct GNUNET_OS_Process *proc) | 208 | GNUNET_OS_process_close (struct GNUNET_OS_Process *proc) |
119 | { | 209 | { |
120 | #if WINDOWS | 210 | #if ENABLE_WINDOWS_WORKAROUNDS |
211 | if (proc->control_pipe) | ||
212 | GNUNET_DISK_npipe_close (proc->control_pipe); | ||
213 | #endif | ||
214 | // FIXME NILS | ||
215 | #ifdef WINDOWS | ||
121 | if (proc->handle != NULL) | 216 | if (proc->handle != NULL) |
122 | CloseHandle (proc->handle); | 217 | CloseHandle (proc->handle); |
123 | #endif | 218 | #endif |
124 | GNUNET_free (proc); | 219 | GNUNET_free (proc); |
125 | } | 220 | } |
126 | 221 | ||
222 | // FIXME NILS | ||
127 | #if WINDOWS | 223 | #if WINDOWS |
128 | #include "gnunet_signal_lib.h" | 224 | #include "gnunet_signal_lib.h" |
129 | 225 | ||
@@ -258,6 +354,105 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, | |||
258 | return GNUNET_OK; | 354 | return GNUNET_OK; |
259 | } | 355 | } |
260 | 356 | ||
357 | #if MINGW | ||
358 | static char * | ||
359 | CreateCustomEnvTable (char **vars) | ||
360 | { | ||
361 | char *win32_env_table, *ptr, **var_ptr, *result, *result_ptr; | ||
362 | size_t tablesize = 0; | ||
363 | size_t items_count = 0; | ||
364 | size_t n_found = 0, n_var; | ||
365 | char *index = NULL; | ||
366 | size_t c; | ||
367 | size_t var_len; | ||
368 | char *var; | ||
369 | char *val; | ||
370 | win32_env_table = GetEnvironmentStringsA (); | ||
371 | if (win32_env_table == NULL) | ||
372 | return NULL; | ||
373 | for (c = 0, var_ptr = vars; *var_ptr; var_ptr += 2, c++); | ||
374 | n_var = c; | ||
375 | index = GNUNET_malloc (n_var); | ||
376 | for (c = 0; c < n_var; c++) | ||
377 | index[c] = 0; | ||
378 | for (items_count = 0, ptr = win32_env_table; ptr[0] != 0; items_count++) | ||
379 | { | ||
380 | size_t len = strlen (ptr); | ||
381 | int found = 0; | ||
382 | for (var_ptr = vars; *var_ptr; var_ptr++) | ||
383 | { | ||
384 | var = *var_ptr++; | ||
385 | val = *var_ptr; | ||
386 | var_len = strlen (var); | ||
387 | if (strncmp (var, ptr, var_len) == 0) | ||
388 | { | ||
389 | found = 1; | ||
390 | index[c] = 1; | ||
391 | tablesize += var_len + strlen (val) + 1; | ||
392 | break; | ||
393 | } | ||
394 | } | ||
395 | if (!found) | ||
396 | tablesize += len + 1; | ||
397 | ptr += len + 1; | ||
398 | } | ||
399 | for (n_found = 0, c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) | ||
400 | { | ||
401 | var = *var_ptr++; | ||
402 | val = *var_ptr; | ||
403 | if (index[c] != 1) | ||
404 | n_found += strlen (var) + strlen (val) + 1; | ||
405 | } | ||
406 | result = GNUNET_malloc (tablesize + n_found + 1); | ||
407 | for (result_ptr = result, ptr = win32_env_table; ptr[0] != 0;) | ||
408 | { | ||
409 | size_t len = strlen (ptr); | ||
410 | int found = 0; | ||
411 | for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) | ||
412 | { | ||
413 | var = *var_ptr++; | ||
414 | val = *var_ptr; | ||
415 | var_len = strlen (var); | ||
416 | if (strncmp (var, ptr, var_len) == 0) | ||
417 | { | ||
418 | found = 1; | ||
419 | break; | ||
420 | } | ||
421 | } | ||
422 | if (!found) | ||
423 | { | ||
424 | strcpy (result_ptr, ptr); | ||
425 | result_ptr += len + 1; | ||
426 | } | ||
427 | else | ||
428 | { | ||
429 | strcpy (result_ptr, var); | ||
430 | result_ptr += var_len; | ||
431 | strcpy (result_ptr, val); | ||
432 | result_ptr += strlen (val) + 1; | ||
433 | } | ||
434 | ptr += len + 1; | ||
435 | } | ||
436 | for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) | ||
437 | { | ||
438 | var = *var_ptr++; | ||
439 | val = *var_ptr; | ||
440 | var_len = strlen (var); | ||
441 | if (index[c] != 1) | ||
442 | { | ||
443 | strcpy (result_ptr, var); | ||
444 | result_ptr += var_len; | ||
445 | strcpy (result_ptr, val); | ||
446 | result_ptr += strlen (val) + 1; | ||
447 | } | ||
448 | } | ||
449 | FreeEnvironmentStrings (win32_env_table); | ||
450 | GNUNET_free (index); | ||
451 | *result_ptr = 0; | ||
452 | return result; | ||
453 | } | ||
454 | #endif | ||
455 | |||
261 | /** | 456 | /** |
262 | * Start a process. | 457 | * Start a process. |
263 | * | 458 | * |
@@ -273,10 +468,14 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
273 | const char *filename, ...) | 468 | const char *filename, ...) |
274 | { | 469 | { |
275 | va_list ap; | 470 | va_list ap; |
471 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
472 | char *childpipename = NULL; | ||
473 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
474 | #endif | ||
475 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
276 | 476 | ||
277 | #ifndef MINGW | 477 | #ifndef MINGW |
278 | pid_t ret; | 478 | pid_t ret; |
279 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
280 | char **argv; | 479 | char **argv; |
281 | int argc; | 480 | int argc; |
282 | int fd_stdout_write; | 481 | int fd_stdout_write; |
@@ -284,6 +483,14 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
284 | int fd_stdin_read; | 483 | int fd_stdin_read; |
285 | int fd_stdin_write; | 484 | int fd_stdin_write; |
286 | 485 | ||
486 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
487 | control_pipe = GNUNET_DISK_npipe_create (&childpipename, | ||
488 | GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | | ||
489 | GNUNET_DISK_PERM_USER_WRITE); | ||
490 | if (control_pipe == NULL) | ||
491 | return NULL; | ||
492 | #endif | ||
493 | |||
287 | argc = 0; | 494 | argc = 0; |
288 | va_start (ap, filename); | 495 | va_start (ap, filename); |
289 | while (NULL != va_arg (ap, char *)) | 496 | while (NULL != va_arg (ap, char *)) |
@@ -316,6 +523,9 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
316 | if (ret == -1) | 523 | if (ret == -1) |
317 | { | 524 | { |
318 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); | 525 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); |
526 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
527 | GNUNET_DISK_npipe_close (control_pipe); | ||
528 | #endif | ||
319 | } | 529 | } |
320 | else | 530 | else |
321 | { | 531 | { |
@@ -337,11 +547,22 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
337 | #endif | 547 | #endif |
338 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 548 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
339 | gnunet_proc->pid = ret; | 549 | gnunet_proc->pid = ret; |
550 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
551 | gnunet_proc->control_pipe = control_pipe; | ||
552 | #endif | ||
340 | } | 553 | } |
341 | GNUNET_free (argv); | 554 | GNUNET_free (argv); |
555 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
556 | GNUNET_free (childpipename); | ||
557 | #endif | ||
342 | return gnunet_proc; | 558 | return gnunet_proc; |
343 | } | 559 | } |
344 | 560 | ||
561 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
562 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); | ||
563 | GNUNET_free (childpipename); | ||
564 | #endif | ||
565 | |||
345 | if (pipe_stdout != NULL) | 566 | if (pipe_stdout != NULL) |
346 | { | 567 | { |
347 | GNUNET_break (0 == close (fd_stdout_read)); | 568 | GNUNET_break (0 == close (fd_stdout_read)); |
@@ -367,23 +588,84 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
367 | char *cmd, *idx; | 588 | char *cmd, *idx; |
368 | STARTUPINFO start; | 589 | STARTUPINFO start; |
369 | PROCESS_INFORMATION proc; | 590 | PROCESS_INFORMATION proc; |
370 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
371 | 591 | ||
372 | HANDLE stdin_handle; | 592 | HANDLE stdin_handle; |
373 | HANDLE stdout_handle; | 593 | HANDLE stdout_handle; |
374 | 594 | ||
375 | char path[MAX_PATH + 1]; | 595 | char path[MAX_PATH + 1]; |
376 | 596 | ||
597 | char *our_env[3] = { NULL, NULL, NULL }; | ||
598 | char *env_block = NULL; | ||
599 | char *pathbuf; | ||
600 | DWORD pathbuf_len, alloc_len; | ||
601 | char *self_prefix; | ||
602 | char *bindir; | ||
603 | char *libdir; | ||
604 | char *ptr; | ||
605 | char *non_const_filename; | ||
606 | |||
607 | /* Search in prefix dir (hopefully - the directory from which | ||
608 | * the current module was loaded), bindir and libdir, then in PATH | ||
609 | */ | ||
610 | self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX); | ||
611 | bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); | ||
612 | libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); | ||
613 | |||
614 | pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0); | ||
615 | |||
616 | alloc_len = pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + strlen (libdir); | ||
617 | |||
618 | pathbuf = GNUNET_malloc (alloc_len * sizeof (char)); | ||
619 | |||
620 | ptr = pathbuf; | ||
621 | ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); | ||
622 | GNUNET_free (self_prefix); | ||
623 | GNUNET_free (bindir); | ||
624 | GNUNET_free (libdir); | ||
625 | |||
626 | alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len); | ||
627 | GNUNET_assert (alloc_len == (pathbuf_len - 1)); | ||
628 | |||
629 | cmdlen = strlen (filename); | ||
630 | if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0) | ||
631 | GNUNET_asprintf (&non_const_filename, "%s.exe", filename); | ||
632 | else | ||
633 | GNUNET_asprintf (&non_const_filename, "%s", filename); | ||
634 | |||
635 | /* Check that this is the full path. If it isn't, search. */ | ||
636 | if (non_const_filename[1] == ':') | ||
637 | snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); | ||
638 | else if (!SearchPathA (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), path, NULL)) | ||
639 | { | ||
640 | SetErrnoFromWinError (GetLastError ()); | ||
641 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "SearchPath", non_const_filename); | ||
642 | GNUNET_free (non_const_filename); | ||
643 | GNUNET_free (pathbuf); | ||
644 | return NULL; | ||
645 | } | ||
646 | GNUNET_free (pathbuf); | ||
647 | GNUNET_free (non_const_filename); | ||
648 | |||
377 | cmdlen = 0; | 649 | cmdlen = 0; |
378 | va_start (ap, filename); | 650 | va_start (ap, filename); |
379 | while (NULL != (arg = va_arg (ap, char *))) | 651 | while (NULL != (arg = va_arg (ap, char *))) |
380 | cmdlen = cmdlen + strlen (arg) + 3; | 652 | { |
653 | if (cmdlen == 0) | ||
654 | cmdlen = cmdlen + strlen (path) + 3; | ||
655 | else | ||
656 | cmdlen = cmdlen + strlen (arg) + 3; | ||
657 | } | ||
381 | va_end (ap); | 658 | va_end (ap); |
382 | 659 | ||
383 | cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); | 660 | cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); |
384 | va_start (ap, filename); | 661 | va_start (ap, filename); |
385 | while (NULL != (arg = va_arg (ap, char *))) | 662 | while (NULL != (arg = va_arg (ap, char *))) |
386 | idx += sprintf (idx, "\"%s\" ", arg); | 663 | { |
664 | if (idx == cmd) | ||
665 | idx += sprintf (idx, "\"%s\" ", path); | ||
666 | else | ||
667 | idx += sprintf (idx, "\"%s\" ", arg); | ||
668 | } | ||
387 | va_end (ap); | 669 | va_end (ap); |
388 | 670 | ||
389 | memset (&start, 0, sizeof (start)); | 671 | memset (&start, 0, sizeof (start)); |
@@ -404,28 +686,46 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
404 | start.hStdOutput = stdout_handle; | 686 | start.hStdOutput = stdout_handle; |
405 | } | 687 | } |
406 | 688 | ||
407 | if (32 >= (int) FindExecutableA (filename, NULL, path)) | 689 | control_pipe = GNUNET_DISK_npipe_create (&childpipename, |
408 | { | 690 | GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | |
409 | SetErrnoFromWinError (GetLastError ()); | 691 | GNUNET_DISK_PERM_USER_WRITE); |
410 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); | 692 | if (control_pipe == NULL) |
411 | return NULL; | 693 | { |
412 | } | 694 | GNUNET_free (cmd); |
695 | GNUNET_free (path); | ||
696 | return NULL; | ||
697 | } | ||
698 | |||
699 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", childpipename); | ||
700 | |||
701 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
702 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | ||
703 | our_env[2] = NULL; | ||
704 | env_block = CreateCustomEnvTable (our_env); | ||
705 | GNUNET_free (our_env[0]); | ||
706 | GNUNET_free (our_env[1]); | ||
413 | 707 | ||
414 | if (!CreateProcessA | 708 | if (!CreateProcessA |
415 | (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start, | 709 | (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED, |
416 | &proc)) | 710 | env_block, NULL, &start, &proc)) |
417 | { | 711 | { |
418 | SetErrnoFromWinError (GetLastError ()); | 712 | SetErrnoFromWinError (GetLastError ()); |
419 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); | 713 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); |
714 | GNUNET_free (env_block); | ||
715 | GNUNET_free (cmd); | ||
420 | return NULL; | 716 | return NULL; |
421 | } | 717 | } |
422 | 718 | ||
719 | GNUNET_free (env_block); | ||
720 | |||
423 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 721 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
424 | gnunet_proc->pid = proc.dwProcessId; | 722 | gnunet_proc->pid = proc.dwProcessId; |
425 | gnunet_proc->handle = proc.hProcess; | 723 | gnunet_proc->handle = proc.hProcess; |
724 | gnunet_proc->control_pipe = control_pipe; | ||
426 | 725 | ||
427 | CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); | 726 | CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); |
428 | 727 | ||
728 | ResumeThread (proc.hThread); | ||
429 | CloseHandle (proc.hThread); | 729 | CloseHandle (proc.hThread); |
430 | 730 | ||
431 | GNUNET_free (cmd); | 731 | GNUNET_free (cmd); |
@@ -450,6 +750,11 @@ struct GNUNET_OS_Process * | |||
450 | GNUNET_OS_start_process_v (const int *lsocks, | 750 | GNUNET_OS_start_process_v (const int *lsocks, |
451 | const char *filename, char *const argv[]) | 751 | const char *filename, char *const argv[]) |
452 | { | 752 | { |
753 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
754 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | ||
755 | char *childpipename = NULL; | ||
756 | #endif | ||
757 | |||
453 | #ifndef MINGW | 758 | #ifndef MINGW |
454 | pid_t ret; | 759 | pid_t ret; |
455 | char lpid[16]; | 760 | char lpid[16]; |
@@ -463,6 +768,14 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
463 | int *lscp; | 768 | int *lscp; |
464 | unsigned int ls; | 769 | unsigned int ls; |
465 | 770 | ||
771 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
772 | control_pipe = GNUNET_DISK_npipe_create (&childpipename, | ||
773 | GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | | ||
774 | GNUNET_DISK_PERM_USER_WRITE); | ||
775 | if (control_pipe == NULL) | ||
776 | return NULL; | ||
777 | #endif | ||
778 | |||
466 | lscp = NULL; | 779 | lscp = NULL; |
467 | ls = 0; | 780 | ls = 0; |
468 | if (lsocks != NULL) | 781 | if (lsocks != NULL) |
@@ -482,6 +795,9 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
482 | if (ret == -1) | 795 | if (ret == -1) |
483 | { | 796 | { |
484 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); | 797 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork"); |
798 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
799 | GNUNET_DISK_npipe_close (control_pipe); | ||
800 | #endif | ||
485 | } | 801 | } |
486 | else | 802 | else |
487 | { | 803 | { |
@@ -498,10 +814,23 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
498 | #endif | 814 | #endif |
499 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 815 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
500 | gnunet_proc->pid = ret; | 816 | gnunet_proc->pid = ret; |
817 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
818 | gnunet_proc->control_pipe = control_pipe; | ||
819 | |||
820 | #endif | ||
501 | } | 821 | } |
502 | GNUNET_array_grow (lscp, ls, 0); | 822 | GNUNET_array_grow (lscp, ls, 0); |
823 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
824 | GNUNET_free (childpipename); | ||
825 | #endif | ||
503 | return gnunet_proc; | 826 | return gnunet_proc; |
504 | } | 827 | } |
828 | |||
829 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
830 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); | ||
831 | GNUNET_free (childpipename); | ||
832 | #endif | ||
833 | |||
505 | if (lscp != NULL) | 834 | if (lscp != NULL) |
506 | { | 835 | { |
507 | /* read systemd documentation... */ | 836 | /* read systemd documentation... */ |
@@ -555,17 +884,68 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
555 | STARTUPINFO start; | 884 | STARTUPINFO start; |
556 | PROCESS_INFORMATION proc; | 885 | PROCESS_INFORMATION proc; |
557 | int argcount = 0; | 886 | int argcount = 0; |
558 | char non_const_filename[MAX_PATH +1]; | ||
559 | struct GNUNET_OS_Process *gnunet_proc = NULL; | 887 | struct GNUNET_OS_Process *gnunet_proc = NULL; |
560 | 888 | ||
889 | char path[MAX_PATH + 1]; | ||
890 | |||
891 | char *our_env[3] = { NULL, NULL, NULL }; | ||
892 | char *env_block = NULL; | ||
893 | char *pathbuf; | ||
894 | DWORD pathbuf_len, alloc_len; | ||
895 | char *self_prefix; | ||
896 | char *bindir; | ||
897 | char *libdir; | ||
898 | char *ptr; | ||
899 | char *non_const_filename; | ||
900 | |||
561 | GNUNET_assert (lsocks == NULL); | 901 | GNUNET_assert (lsocks == NULL); |
562 | 902 | ||
563 | if (32 >= (int) FindExecutableA (filename, NULL, non_const_filename)) | 903 | /* Search in prefix dir (hopefully - the directory from which |
904 | * the current module was loaded), bindir and libdir, then in PATH | ||
905 | */ | ||
906 | self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX); | ||
907 | bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); | ||
908 | libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); | ||
909 | |||
910 | pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0); | ||
911 | |||
912 | alloc_len = pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + strlen (libdir); | ||
913 | |||
914 | pathbuf = GNUNET_malloc (alloc_len * sizeof (char)); | ||
915 | |||
916 | ptr = pathbuf; | ||
917 | ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); | ||
918 | GNUNET_free (self_prefix); | ||
919 | GNUNET_free (bindir); | ||
920 | GNUNET_free (libdir); | ||
921 | |||
922 | alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len); | ||
923 | if (alloc_len != pathbuf_len - 1) | ||
924 | { | ||
925 | GNUNET_free (pathbuf); | ||
926 | errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */ | ||
927 | return NULL; | ||
928 | } | ||
929 | |||
930 | cmdlen = strlen (filename); | ||
931 | if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0) | ||
932 | GNUNET_asprintf (&non_const_filename, "%s.exe", filename); | ||
933 | else | ||
934 | GNUNET_asprintf (&non_const_filename, "%s", filename); | ||
935 | |||
936 | /* Check that this is the full path. If it isn't, search. */ | ||
937 | if (non_const_filename[1] == ':') | ||
938 | snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); | ||
939 | else if (!SearchPathA (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), path, NULL)) | ||
564 | { | 940 | { |
565 | SetErrnoFromWinError (GetLastError ()); | 941 | SetErrnoFromWinError (GetLastError ()); |
566 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); | 942 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "SearchPath", non_const_filename); |
943 | GNUNET_free (non_const_filename); | ||
944 | GNUNET_free (pathbuf); | ||
567 | return NULL; | 945 | return NULL; |
568 | } | 946 | } |
947 | GNUNET_free (pathbuf); | ||
948 | GNUNET_free (non_const_filename); | ||
569 | 949 | ||
570 | /* Count the number of arguments */ | 950 | /* Count the number of arguments */ |
571 | arg = (char **) argv; | 951 | arg = (char **) argv; |
@@ -583,7 +963,10 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
583 | arg = (char **) argv; | 963 | arg = (char **) argv; |
584 | while (*arg) | 964 | while (*arg) |
585 | { | 965 | { |
586 | non_const_argv[argcount] = GNUNET_strdup (*arg); | 966 | if (arg == argv) |
967 | non_const_argv[argcount] = GNUNET_strdup (path); | ||
968 | else | ||
969 | non_const_argv[argcount] = GNUNET_strdup (*arg); | ||
587 | arg++; | 970 | arg++; |
588 | argcount++; | 971 | argcount++; |
589 | } | 972 | } |
@@ -607,31 +990,56 @@ GNUNET_OS_start_process_v (const int *lsocks, | |||
607 | arg++; | 990 | arg++; |
608 | } | 991 | } |
609 | 992 | ||
993 | while (argcount > 0) | ||
994 | GNUNET_free (non_const_argv[--argcount]); | ||
995 | GNUNET_free (non_const_argv); | ||
996 | |||
610 | memset (&start, 0, sizeof (start)); | 997 | memset (&start, 0, sizeof (start)); |
611 | start.cb = sizeof (start); | 998 | start.cb = sizeof (start); |
612 | 999 | ||
1000 | control_pipe = GNUNET_DISK_npipe_create (&childpipename, | ||
1001 | GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | | ||
1002 | GNUNET_DISK_PERM_USER_WRITE); | ||
1003 | if (control_pipe == NULL) | ||
1004 | { | ||
1005 | GNUNET_free (cmd); | ||
1006 | GNUNET_free (path); | ||
1007 | return NULL; | ||
1008 | } | ||
1009 | |||
1010 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", childpipename); | ||
1011 | |||
1012 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
1013 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | ||
1014 | our_env[2] = NULL; | ||
1015 | env_block = CreateCustomEnvTable (our_env); | ||
1016 | GNUNET_free (our_env[0]); | ||
1017 | GNUNET_free (our_env[1]); | ||
1018 | |||
613 | if (!CreateProcess | 1019 | if (!CreateProcess |
614 | (non_const_filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start, | 1020 | (path, cmd, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED, |
615 | &proc)) | 1021 | env_block, NULL, &start, &proc)) |
616 | { | 1022 | { |
617 | SetErrnoFromWinError (GetLastError ()); | 1023 | SetErrnoFromWinError (GetLastError ()); |
618 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); | 1024 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); |
1025 | GNUNET_free (env_block); | ||
1026 | GNUNET_free (cmd); | ||
619 | return NULL; | 1027 | return NULL; |
620 | } | 1028 | } |
621 | 1029 | ||
1030 | GNUNET_free (env_block); | ||
1031 | |||
622 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 1032 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
623 | gnunet_proc->pid = proc.dwProcessId; | 1033 | gnunet_proc->pid = proc.dwProcessId; |
624 | gnunet_proc->handle = proc.hProcess; | 1034 | gnunet_proc->handle = proc.hProcess; |
1035 | gnunet_proc->control_pipe = control_pipe; | ||
625 | 1036 | ||
626 | CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); | 1037 | CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); |
627 | 1038 | ||
1039 | ResumeThread (proc.hThread); | ||
628 | CloseHandle (proc.hThread); | 1040 | CloseHandle (proc.hThread); |
629 | GNUNET_free (cmd); | 1041 | GNUNET_free (cmd); |
630 | 1042 | ||
631 | while (argcount > 0) | ||
632 | GNUNET_free (non_const_argv[--argcount]); | ||
633 | GNUNET_free (non_const_argv); | ||
634 | |||
635 | return gnunet_proc; | 1043 | return gnunet_proc; |
636 | #endif | 1044 | #endif |
637 | } | 1045 | } |
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 8a6479929..2d7907395 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -739,6 +739,11 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
739 | GNUNET_SCHEDULER_add_continuation (task, | 739 | GNUNET_SCHEDULER_add_continuation (task, |
740 | task_cls, | 740 | task_cls, |
741 | GNUNET_SCHEDULER_REASON_STARTUP); | 741 | GNUNET_SCHEDULER_REASON_STARTUP); |
742 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
743 | GNUNET_SCHEDULER_add_continuation (GNUNET_OS_install_parent_control_handler, | ||
744 | NULL, GNUNET_SCHEDULER_REASON_STARTUP); | ||
745 | #endif | ||
746 | |||
742 | last_tr = 0; | 747 | last_tr = 0; |
743 | busy_wait_warning = 0; | 748 | busy_wait_warning = 0; |
744 | while ((pending != NULL) || | 749 | while ((pending != NULL) || |