aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-14 23:18:06 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-14 23:18:06 +0000
commit91ab799c42b2496e65afd0c866811999d88119ed (patch)
tree2c31aa87ead94723c1d959a691b11811fc4589f8 /src/util
parenta72a1c6fc09216c5be7f5ee697ff55cf66907c80 (diff)
downloadgnunet-91ab799c42b2496e65afd0c866811999d88119ed.tar.gz
gnunet-91ab799c42b2496e65afd0c866811999d88119ed.zip
LRN: enable more fine-grained control over blocking/non-blocking pipe operation
Diffstat (limited to 'src/util')
-rw-r--r--src/util/disk.c161
-rw-r--r--src/util/helper.c4
-rw-r--r--src/util/os_priority.c4
-rw-r--r--src/util/scheduler.c2
-rw-r--r--src/util/test_common_logging_runtime_loglevels.c2
-rw-r--r--src/util/test_os_start_process.c4
-rw-r--r--src/util/test_scheduler.c2
7 files changed, 143 insertions, 36 deletions
diff --git a/src/util/disk.c b/src/util/disk.c
index eb707fd62..a5190d587 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -746,6 +746,74 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result,
746#endif 746#endif
747} 747}
748 748
749/**
750 * Read the contents of a binary file into a buffer.
751 * Guarantees not to block (returns GNUNET_SYSERR and sets errno to EAGAIN
752 * when no data can be read).
753 *
754 * @param h handle to an open file
755 * @param result the buffer to write the result to
756 * @param len the maximum number of bytes to read
757 * @return the number of bytes read on success, GNUNET_SYSERR on failure
758 */
759ssize_t
760GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h,
761 void *result, size_t len)
762{
763 if (h == NULL)
764 {
765 errno = EINVAL;
766 return GNUNET_SYSERR;
767 }
768
769#ifdef MINGW
770 DWORD bytesRead;
771
772 if (h->type != GNUNET_PIPE)
773 {
774 if (!ReadFile (h->h, result, len, &bytesRead, NULL))
775 {
776 SetErrnoFromWinError (GetLastError ());
777 return GNUNET_SYSERR;
778 }
779 }
780 else
781 {
782#if DEBUG_PIPE
783 LOG (GNUNET_ERROR_TYPE_DEBUG, "It is a pipe, trying to read\n");
784#endif
785 if (!ReadFile (h->h, result, len, &bytesRead, h->oOverlapRead))
786 {
787 if (GetLastError () != ERROR_IO_PENDING)
788 {
789#if DEBUG_PIPE
790 LOG (GNUNET_ERROR_TYPE_DEBUG, "Error reading from pipe: %u\n", GetLastError ());
791#endif
792 SetErrnoFromWinError (GetLastError ());
793 return GNUNET_SYSERR;
794 }
795 else
796 {
797#if DEBUG_PIPE
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "ReadFile() queued a read, cancelling\n");
800#endif
801 CancelIo (h->h);
802 errno = EAGAIN;
803 return GNUNET_SYSERR;
804 }
805 }
806#if DEBUG_PIPE
807 LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes\n", bytesRead);
808#endif
809 }
810 return bytesRead;
811#else
812 /* FIXME: set to non-blocking (fcntl?), read, then set back? */
813 return read (h->fd, result, len);
814#endif
815}
816
749 817
750/** 818/**
751 * Read the contents of a binary file into a buffer. 819 * Read the contents of a binary file into a buffer.
@@ -871,6 +939,64 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h,
871} 939}
872 940
873/** 941/**
942 * Write a buffer to a file, blocking, if necessary.
943 * @param h handle to open file
944 * @param buffer the data to write
945 * @param n number of bytes to write
946 * @return number of bytes written on success, GNUNET_SYSERR on error
947 */
948ssize_t
949GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h,
950 const void *buffer, size_t n)
951{
952 if (h == NULL)
953 {
954 errno = EINVAL;
955 return GNUNET_SYSERR;
956 }
957
958#ifdef MINGW
959 DWORD bytesWritten;
960 /* We do a non-overlapped write, which is as blocking as it gets */
961#if DEBUG_PIPE
962 LOG (GNUNET_ERROR_TYPE_DEBUG, "Writing %u bytes\n", n);
963#endif
964 if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL))
965 {
966 SetErrnoFromWinError (GetLastError ());
967#if DEBUG_PIPE
968 LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n",
969 GetLastError ());
970#endif
971 return GNUNET_SYSERR;
972 }
973 if (bytesWritten == 0 && n > 0)
974 {
975#if DEBUG_PIPE
976 LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for pipe to clean\n");
977#endif
978 WaitForSingleObject (h->h, INFINITE);
979 if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL))
980 {
981 SetErrnoFromWinError (GetLastError ());
982#if DEBUG_PIPE
983 LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n",
984 GetLastError ());
985#endif
986 return GNUNET_SYSERR;
987 }
988 }
989#if DEBUG_PIPE
990 LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytesWritten);
991#endif
992 return bytesWritten;
993#else
994 /* FIXME: switch to blocking mode (fcntl?), write, then switch back? */
995 return write (h->fd, buffer, n);
996#endif
997}
998
999/**
874 * Write a buffer to a file. If the file is longer than the 1000 * Write a buffer to a file. If the file is longer than the
875 * number of bytes that will be written, it will be truncated. 1001 * number of bytes that will be written, it will be truncated.
876 * 1002 *
@@ -1971,7 +2097,7 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
1971 * @return handle to the new pipe, NULL on error 2097 * @return handle to the new pipe, NULL on error
1972 */ 2098 */
1973struct GNUNET_DISK_PipeHandle * 2099struct GNUNET_DISK_PipeHandle *
1974GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write) 2100GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int inherit_write)
1975{ 2101{
1976 struct GNUNET_DISK_PipeHandle *p; 2102 struct GNUNET_DISK_PipeHandle *p;
1977 struct GNUNET_DISK_FileHandle *fds; 2103 struct GNUNET_DISK_FileHandle *fds;
@@ -2000,7 +2126,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
2000 p->fd[1]->fd = fd[1]; 2126 p->fd[1]->fd = fd[1];
2001 ret = 0; 2127 ret = 0;
2002 flags = fcntl (fd[0], F_GETFL); 2128 flags = fcntl (fd[0], F_GETFL);
2003 if (!blocking) 2129 if (!blocking_read)
2004 flags |= O_NONBLOCK; 2130 flags |= O_NONBLOCK;
2005 if (0 > fcntl (fd[0], F_SETFL, flags)) 2131 if (0 > fcntl (fd[0], F_SETFL, flags))
2006 ret = -1; 2132 ret = -1;
@@ -2010,7 +2136,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
2010 ret = -1; 2136 ret = -1;
2011 2137
2012 flags = fcntl (fd[1], F_GETFL); 2138 flags = fcntl (fd[1], F_GETFL);
2013 if (!blocking) 2139 if (!blocking_write)
2014 flags |= O_NONBLOCK; 2140 flags |= O_NONBLOCK;
2015 if (0 > fcntl (fd[1], F_SETFL, flags)) 2141 if (0 > fcntl (fd[1], F_SETFL, flags))
2016 ret = -1; 2142 ret = -1;
@@ -2034,7 +2160,8 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
2034 2160
2035 ret = 2161 ret =
2036 create_selectable_pipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0, 2162 create_selectable_pipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0,
2037 FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED); 2163 blocking_read ? 0 : FILE_FLAG_OVERLAPPED,
2164 blocking_write ? 0 : FILE_FLAG_OVERLAPPED);
2038 if (!ret) 2165 if (!ret)
2039 { 2166 {
2040 GNUNET_free (p); 2167 GNUNET_free (p);
@@ -2066,15 +2193,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
2066 } 2193 }
2067 CloseHandle (p->fd[1]->h); 2194 CloseHandle (p->fd[1]->h);
2068 p->fd[1]->h = tmp_handle; 2195 p->fd[1]->h = tmp_handle;
2069 if (!blocking)
2070 {
2071 DWORD mode;
2072 2196
2073 mode = PIPE_NOWAIT;
2074 SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL);
2075 SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL);
2076 /* this always fails on Windows 95, so we don't care about error handling */
2077 }
2078 p->fd[0]->type = GNUNET_PIPE; 2197 p->fd[0]->type = GNUNET_PIPE;
2079 p->fd[1]->type = GNUNET_PIPE; 2198 p->fd[1]->type = GNUNET_PIPE;
2080 2199
@@ -2103,7 +2222,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
2103 * @return handle to the new pipe, NULL on error 2222 * @return handle to the new pipe, NULL on error
2104 */ 2223 */
2105struct GNUNET_DISK_PipeHandle * 2224struct GNUNET_DISK_PipeHandle *
2106GNUNET_DISK_pipe_from_fd (int blocking, int fd[2]) 2225GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
2107{ 2226{
2108 struct GNUNET_DISK_PipeHandle *p; 2227 struct GNUNET_DISK_PipeHandle *p;
2109 struct GNUNET_DISK_FileHandle *fds; 2228 struct GNUNET_DISK_FileHandle *fds;
@@ -2124,7 +2243,7 @@ GNUNET_DISK_pipe_from_fd (int blocking, int fd[2])
2124 if (fd[0] >= 0) 2243 if (fd[0] >= 0)
2125 { 2244 {
2126 flags = fcntl (fd[0], F_GETFL); 2245 flags = fcntl (fd[0], F_GETFL);
2127 if (!blocking) 2246 if (!blocking_read)
2128 flags |= O_NONBLOCK; 2247 flags |= O_NONBLOCK;
2129 if (0 > fcntl (fd[0], F_SETFL, flags)) 2248 if (0 > fcntl (fd[0], F_SETFL, flags))
2130 ret = -1; 2249 ret = -1;
@@ -2137,7 +2256,7 @@ GNUNET_DISK_pipe_from_fd (int blocking, int fd[2])
2137 if (fd[1] >= 0) 2256 if (fd[1] >= 0)
2138 { 2257 {
2139 flags = fcntl (fd[1], F_GETFL); 2258 flags = fcntl (fd[1], F_GETFL);
2140 if (!blocking) 2259 if (!blocking_write)
2141 flags |= O_NONBLOCK; 2260 flags |= O_NONBLOCK;
2142 if (0 > fcntl (fd[1], F_SETFL, flags)) 2261 if (0 > fcntl (fd[1], F_SETFL, flags))
2143 ret = -1; 2262 ret = -1;
@@ -2170,18 +2289,6 @@ GNUNET_DISK_pipe_from_fd (int blocking, int fd[2])
2170 else 2289 else
2171 p->fd[1]->h = INVALID_HANDLE_VALUE; 2290 p->fd[1]->h = INVALID_HANDLE_VALUE;
2172 2291
2173 if (!blocking)
2174 {
2175 DWORD mode;
2176
2177 mode = PIPE_NOWAIT;
2178 if (p->fd[0]->h != INVALID_HANDLE_VALUE)
2179 SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL);
2180 if (p->fd[1]->h != INVALID_HANDLE_VALUE)
2181 SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL);
2182 /* this always fails on Windows 95, so we don't care about error handling */
2183 }
2184
2185 if (p->fd[0]->h != INVALID_HANDLE_VALUE) 2292 if (p->fd[0]->h != INVALID_HANDLE_VALUE)
2186 { 2293 {
2187 p->fd[0]->type = GNUNET_PIPE; 2294 p->fd[0]->type = GNUNET_PIPE;
diff --git a/src/util/helper.c b/src/util/helper.c
index d4d26ba51..d0aab3ccf 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -286,8 +286,8 @@ helper_read (void *cls,
286static void 286static void
287start_helper (struct GNUNET_HELPER_Handle *h) 287start_helper (struct GNUNET_HELPER_Handle *h)
288{ 288{
289 h->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); 289 h->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
290 h->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); 290 h->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
291 if ( (h->helper_in == NULL) || (h->helper_out == NULL)) 291 if ( (h->helper_in == NULL) || (h->helper_out == NULL))
292 { 292 {
293 /* out of file descriptors? try again later... */ 293 /* out of file descriptors? try again later... */
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index 13f002f5d..b344cd862 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -1135,7 +1135,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
1135 } 1135 }
1136 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) 1136 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
1137 { 1137 {
1138 lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); 1138 lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
1139 1139
1140 if (lsocks_pipe == NULL) 1140 if (lsocks_pipe == NULL)
1141 { 1141 {
@@ -1582,7 +1582,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls,
1582 struct GNUNET_DISK_PipeHandle *opipe; 1582 struct GNUNET_DISK_PipeHandle *opipe;
1583 va_list ap; 1583 va_list ap;
1584 1584
1585 opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); 1585 opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
1586 if (NULL == opipe) 1586 if (NULL == opipe)
1587 return NULL; 1587 return NULL;
1588 va_start (ap, binary); 1588 va_start (ap, binary);
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 5f91ffbbc..412896946 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -803,7 +803,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
803 rs = GNUNET_NETWORK_fdset_create (); 803 rs = GNUNET_NETWORK_fdset_create ();
804 ws = GNUNET_NETWORK_fdset_create (); 804 ws = GNUNET_NETWORK_fdset_create ();
805 GNUNET_assert (shutdown_pipe_handle == NULL); 805 GNUNET_assert (shutdown_pipe_handle == NULL);
806 shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO); 806 shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
807 GNUNET_assert (shutdown_pipe_handle != NULL); 807 GNUNET_assert (shutdown_pipe_handle != NULL);
808 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, 808 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
809 GNUNET_DISK_PIPE_END_READ); 809 GNUNET_DISK_PIPE_END_READ);
diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c
index 51123d9b3..092f06041 100644
--- a/src/util/test_common_logging_runtime_loglevels.c
+++ b/src/util/test_common_logging_runtime_loglevels.c
@@ -268,7 +268,7 @@ runone ()
268{ 268{
269 const struct GNUNET_DISK_FileHandle *stdout_read_handle; 269 const struct GNUNET_DISK_FileHandle *stdout_read_handle;
270 270
271 pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); 271 pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
272 272
273 if (pipe_stdout == NULL) 273 if (pipe_stdout == NULL)
274 { 274 {
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c
index 78538404a..f66e741d9 100644
--- a/src/util/test_os_start_process.c
+++ b/src/util/test_os_start_process.c
@@ -114,8 +114,8 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
114 114
115 GNUNET_asprintf (&fn, "cat"); 115 GNUNET_asprintf (&fn, "cat");
116 116
117 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); 117 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
118 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); 118 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
119 119
120 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) 120 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
121 { 121 {
diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c
index 788ba13fa..8072feaf1 100644
--- a/src/util/test_scheduler.c
+++ b/src/util/test_scheduler.c
@@ -119,7 +119,7 @@ task5 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
119 119
120 GNUNET_assert (5 == *ok); 120 GNUNET_assert (5 == *ok);
121 (*ok) = 6; 121 (*ok) = 6;
122 p = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO); 122 p = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
123 GNUNET_assert (NULL != p); 123 GNUNET_assert (NULL != p);
124 fds[0] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_READ); 124 fds[0] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_READ);
125 fds[1] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_WRITE); 125 fds[1] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_WRITE);