summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/helper/options.c6
-rw-r--r--src/helper/replacements.c152
-rw-r--r--src/helper/replacements.h12
-rw-r--r--src/server/gdb_server.c2
-rw-r--r--src/server/server.c20
5 files changed, 180 insertions, 12 deletions
diff --git a/src/helper/options.c b/src/helper/options.c
index 203791bd..dd9f7138 100644
--- a/src/helper/options.c
+++ b/src/helper/options.c
@@ -149,14 +149,8 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
/* pipes unsupported on hosted platforms */
LOG_WARNING("pipes not supported on this platform");
#else
-#ifdef IS_MINGW
- /* pipes currently unsupported on win32 */
- LOG_WARNING("pipes currently unsupported on win32");
- exit(1);
-#else
server_use_pipes = 1;
#endif
-#endif
break;
}
}
diff --git a/src/helper/replacements.c b/src/helper/replacements.c
index b6ddfd7c..39a736c7 100644
--- a/src/helper/replacements.c
+++ b/src/helper/replacements.c
@@ -68,6 +68,10 @@ void *fill_malloc(size_t size)
#include <stdio.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+
/* replacements for gettimeofday */
#ifndef HAVE_GETTIMEOFDAY
@@ -137,3 +141,151 @@ char* strndup(const char *s, size_t n)
return (char *) memcpy (new, s, len);
}
#endif
+
+#ifdef _WIN32
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+ DWORD ms_total, limit;
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
+ int n_handles = 0, i;
+ fd_set sock_read, sock_write, sock_except;
+ fd_set aread, awrite, aexcept;
+ int sock_max_fd = -1;
+ struct timeval tvslice;
+ int retcode;
+
+#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
+
+ /* calculate how long we need to wait in milliseconds */
+ if (tv == NULL) {
+ ms_total = INFINITE;
+ } else {
+ ms_total = tv->tv_sec * 1000;
+ ms_total += tv->tv_usec / 1000;
+ }
+
+ FD_ZERO(&sock_read);
+ FD_ZERO(&sock_write);
+ FD_ZERO(&sock_except);
+
+ /* build an array of handles for non-sockets */
+ for (i = 0; i < max_fd; i++) {
+ if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
+ handles[n_handles] = (HANDLE)_get_osfhandle(i);
+ if (handles[n_handles] == INVALID_HANDLE_VALUE) {
+ /* socket */
+ if (SAFE_FD_ISSET(i, rfds)) {
+ FD_SET(i, &sock_read);
+ }
+ if (SAFE_FD_ISSET(i, wfds)) {
+ FD_SET(i, &sock_write);
+ }
+ if (SAFE_FD_ISSET(i, efds)) {
+ FD_SET(i, &sock_except);
+ }
+ if (i > sock_max_fd) {
+ sock_max_fd = i;
+ }
+ } else {
+ handle_slot_to_fd[n_handles] = i;
+ n_handles++;
+ }
+ }
+ }
+
+ if (n_handles == 0) {
+ /* plain sockets only - let winsock handle the whole thing */
+ return select(max_fd, rfds, wfds, efds, tv);
+ }
+
+ /* mixture of handles and sockets; lets multiplex between
+ * winsock and waiting on the handles */
+
+ FD_ZERO(&aread);
+ FD_ZERO(&awrite);
+ FD_ZERO(&aexcept);
+
+ limit = GetTickCount() + ms_total;
+ do {
+ retcode = 0;
+
+ if (sock_max_fd >= 0) {
+ /* overwrite the zero'd sets here; the select call
+ * will clear those that are not active */
+ aread = sock_read;
+ awrite = sock_write;
+ aexcept = sock_except;
+
+ tvslice.tv_sec = 0;
+ tvslice.tv_usec = 100000;
+
+ retcode = select(sock_max_fd+1, &aread, &awrite, &aexcept, &tvslice);
+ }
+ if (n_handles > 0) {
+ /* check handles */
+ DWORD wret;
+
+ wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 100, QS_ALLEVENTS);
+
+ if (wret == WAIT_TIMEOUT) {
+ /* set retcode to 0; this is the default.
+ * select() may have set it to something else,
+ * in which case we leave it alone, so this branch
+ * does nothing */
+ ;
+ } else if (wret == WAIT_FAILED) {
+ if (retcode == 0) {
+ retcode = -1;
+ }
+ } else {
+ if (retcode < 0) {
+ retcode = 0;
+ }
+ for (i = 0; i < n_handles; i++) {
+ if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
+ if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
+ DWORD dwBytes;
+
+ if (PeekNamedPipe((HANDLE)_get_osfhandle(handle_slot_to_fd[i]), NULL, 0, NULL, &dwBytes, NULL))
+ {
+ /* check to see if gdb pipe has data available */
+ if (dwBytes)
+ {
+ FD_SET(handle_slot_to_fd[i], &aread);
+ retcode++;
+ }
+ }
+ else
+ {
+ FD_SET(handle_slot_to_fd[i], &aread);
+ retcode++;
+ }
+ }
+ if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
+ FD_SET(handle_slot_to_fd[i], &awrite);
+ retcode++;
+ }
+ if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) {
+ FD_SET(handle_slot_to_fd[i], &aexcept);
+ retcode++;
+ }
+ }
+ }
+ }
+ }
+ } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
+
+ if (rfds) {
+ *rfds = aread;
+ }
+ if (wfds) {
+ *wfds = awrite;
+ }
+ if (efds) {
+ *efds = aexcept;
+ }
+
+ return retcode;
+}
+#endif
diff --git a/src/helper/replacements.h b/src/helper/replacements.h
index b6165085..c3a2bf77 100644
--- a/src/helper/replacements.h
+++ b/src/helper/replacements.h
@@ -180,6 +180,9 @@ static __inline void outb(unsigned char value, unsigned short int port)
}
#endif /* IS_MINGW */
+
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv);
+
#endif /* _WIN32 */
/* generic socket functions for Windows and Posix */
@@ -221,6 +224,15 @@ static __inline void socket_nonblock(int fd)
#endif
}
+static __inline int socket_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+#ifdef _WIN32
+ return win_select(max_fd, rfds, wfds, efds, tv);
+#else
+ return select(max_fd, rfds, wfds, efds, tv);
+#endif
+}
+
#ifndef HAVE_ELF_H
typedef struct
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 3f9e1e71..eb612c7a 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -126,7 +126,7 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
tv.tv_sec = timeout_s;
tv.tv_usec = 0;
- if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
+ if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
{
/* This can typically be because a "monitor" command took too long
* before printing any progress messages
diff --git a/src/server/server.c b/src/server/server.c
index b5b9a205..e97dac9a 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -97,12 +97,11 @@ int add_connection(service_t *service, command_context_t *cmd_ctx)
}
else if (service->type == CONNECTION_PIPE)
{
-#ifndef _WIN32
c->fd = service->fd;
/* do not check for new connections again on stdin */
service->fd = -1;
-#endif
+
LOG_INFO("accepting '%s' connection from pipe", service->name);
if ((retval = service->new_connection(c)) != ERROR_OK)
{
@@ -223,6 +222,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
LOG_WARNING("cannot change stdout mode to binary");
if (_setmode(_fileno(stdin), _O_BINARY) < 0)
LOG_WARNING("cannot change stdin mode to binary");
+ if (_setmode(_fileno(stderr), _O_BINARY) < 0)
+ LOG_WARNING("cannot change stderr mode to binary");
#else
socket_nonblock(c->fd);
#endif
@@ -365,7 +366,7 @@ int server_loop(command_context_t *command_context)
kept_alive();
/* Only while we're sleeping we'll let others run */
- retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+ retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
openocd_sleep_postlude();
if (retval == -1)
@@ -503,7 +504,7 @@ int server_init(void)
WORD wVersionRequested;
WSADATA wsaData;
- wVersionRequested = MAKEWORD( 2, 2 );
+ wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
@@ -511,7 +512,16 @@ int server_init(void)
exit(-1);
}
- SetConsoleCtrlHandler( ControlHandler, TRUE );
+ if (server_use_pipes == 0)
+ {
+ /* register ctrl-c handler */
+ SetConsoleCtrlHandler(ControlHandler, TRUE);
+ }
+ else
+ {
+ /* we are using pipes so ignore ctrl-c */
+ SetConsoleCtrlHandler(NULL, TRUE);
+ }
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);