Merge pull request #1563 from nicolasnoble/more-win32-fixes

Various Win32 fixes and improvements.
pull/1572/head
Craig Tiller 10 years ago
commit 52c6801cfb
  1. 2
      src/core/iomgr/endpoint_pair_windows.c
  2. 1
      src/core/iomgr/iocp_windows.h
  3. 6
      src/core/iomgr/socket_windows.c
  4. 4
      src/core/iomgr/socket_windows.h
  5. 30
      src/core/iomgr/tcp_windows.c
  6. 7
      templates/vsprojects/Grpc.mak.template
  7. 4
      templates/vsprojects/vcxproj_defs.include
  8. 6
      tools/run_tests/run_tests.py
  9. 1296
      vsprojects/Grpc.mak

@ -56,6 +56,8 @@ static void create_sockets(SOCKET sv[2]) {
GPR_ASSERT(lst_sock != INVALID_SOCKET); GPR_ASSERT(lst_sock != INVALID_SOCKET);
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_family = AF_INET;
GPR_ASSERT(bind(lst_sock, (struct sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR); GPR_ASSERT(bind(lst_sock, (struct sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR);
GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR); GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR);
GPR_ASSERT(getsockname(lst_sock, (struct sockaddr*)&addr, &addr_len) != SOCKET_ERROR); GPR_ASSERT(getsockname(lst_sock, (struct sockaddr*)&addr, &addr_len) != SOCKET_ERROR);

@ -40,6 +40,7 @@
#include "src/core/iomgr/socket_windows.h" #include "src/core/iomgr/socket_windows.h"
void grpc_iocp_init(void); void grpc_iocp_init(void);
void grpc_iocp_kick(void);
void grpc_iocp_shutdown(void); void grpc_iocp_shutdown(void);
void grpc_iocp_add_socket(grpc_winsocket *); void grpc_iocp_add_socket(grpc_winsocket *);
void grpc_iocp_socket_orphan(grpc_winsocket *); void grpc_iocp_socket_orphan(grpc_winsocket *);

@ -59,17 +59,21 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket) {
operations to abort them. We need to do that this way because of the operations to abort them. We need to do that this way because of the
various callsites of that function, which happens to be in various various callsites of that function, which happens to be in various
mutex hold states, and that'd be unsafe to call them directly. */ mutex hold states, and that'd be unsafe to call them directly. */
void grpc_winsocket_shutdown(grpc_winsocket *socket) { int grpc_winsocket_shutdown(grpc_winsocket *socket) {
int callbacks_set = 0;
gpr_mu_lock(&socket->state_mu); gpr_mu_lock(&socket->state_mu);
if (socket->read_info.cb) { if (socket->read_info.cb) {
callbacks_set++;
grpc_iomgr_add_delayed_callback(socket->read_info.cb, grpc_iomgr_add_delayed_callback(socket->read_info.cb,
socket->read_info.opaque, 0); socket->read_info.opaque, 0);
} }
if (socket->write_info.cb) { if (socket->write_info.cb) {
callbacks_set++;
grpc_iomgr_add_delayed_callback(socket->write_info.cb, grpc_iomgr_add_delayed_callback(socket->write_info.cb,
socket->write_info.opaque, 0); socket->write_info.opaque, 0);
} }
gpr_mu_unlock(&socket->state_mu); gpr_mu_unlock(&socket->state_mu);
return callbacks_set;
} }
/* Abandons a socket. Either we're going to queue it up for garbage collecting /* Abandons a socket. Either we're going to queue it up for garbage collecting

@ -100,8 +100,8 @@ typedef struct grpc_winsocket {
grpc_winsocket *grpc_winsocket_create(SOCKET socket); grpc_winsocket *grpc_winsocket_create(SOCKET socket);
/* Initiate an asynchronous shutdown of the socket. Will call off any pending /* Initiate an asynchronous shutdown of the socket. Will call off any pending
operation to cancel them. */ operation to cancel them. Returns the number of callbacks that got setup. */
void grpc_winsocket_shutdown(grpc_winsocket *socket); int grpc_winsocket_shutdown(grpc_winsocket *socket);
/* Abandon a socket. */ /* Abandon a socket. */
void grpc_winsocket_orphan(grpc_winsocket *socket); void grpc_winsocket_orphan(grpc_winsocket *socket);

@ -118,12 +118,14 @@ static void on_read(void *tcpp, int from_iocp) {
gpr_slice *slice = NULL; gpr_slice *slice = NULL;
size_t nslices = 0; size_t nslices = 0;
grpc_endpoint_cb_status status; grpc_endpoint_cb_status status;
grpc_endpoint_read_cb cb = tcp->read_cb; grpc_endpoint_read_cb cb;
grpc_winsocket_callback_info *info = &socket->read_info; grpc_winsocket_callback_info *info = &socket->read_info;
void *opaque = tcp->read_user_data; void *opaque = tcp->read_user_data;
int do_abort = 0; int do_abort = 0;
gpr_mu_lock(&tcp->mu); gpr_mu_lock(&tcp->mu);
cb = tcp->read_cb;
tcp->read_cb = NULL;
if (!from_iocp || tcp->shutting_down) { if (!from_iocp || tcp->shutting_down) {
/* If we are here with from_iocp set to true, it means we got raced to /* If we are here with from_iocp set to true, it means we got raced to
shutting down the endpoint. No actual abort callback will happen shutting down the endpoint. No actual abort callback will happen
@ -133,9 +135,12 @@ static void on_read(void *tcpp, int from_iocp) {
gpr_mu_unlock(&tcp->mu); gpr_mu_unlock(&tcp->mu);
if (do_abort) { if (do_abort) {
if (from_iocp) gpr_slice_unref(tcp->read_slice); if (from_iocp) {
tcp->socket->read_info.outstanding = 0;
gpr_slice_unref(tcp->read_slice);
}
tcp_unref(tcp); tcp_unref(tcp);
cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); if (cb) cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN);
return; return;
} }
@ -225,11 +230,13 @@ static void on_write(void *tcpp, int from_iocp) {
grpc_winsocket *handle = tcp->socket; grpc_winsocket *handle = tcp->socket;
grpc_winsocket_callback_info *info = &handle->write_info; grpc_winsocket_callback_info *info = &handle->write_info;
grpc_endpoint_cb_status status = GRPC_ENDPOINT_CB_OK; grpc_endpoint_cb_status status = GRPC_ENDPOINT_CB_OK;
grpc_endpoint_write_cb cb = tcp->write_cb; grpc_endpoint_write_cb cb;
void *opaque = tcp->write_user_data; void *opaque = tcp->write_user_data;
int do_abort = 0; int do_abort = 0;
gpr_mu_lock(&tcp->mu); gpr_mu_lock(&tcp->mu);
cb = tcp->write_cb;
tcp->write_cb = NULL;
if (!from_iocp || tcp->shutting_down) { if (!from_iocp || tcp->shutting_down) {
/* If we are here with from_iocp set to true, it means we got raced to /* If we are here with from_iocp set to true, it means we got raced to
shutting down the endpoint. No actual abort callback will happen shutting down the endpoint. No actual abort callback will happen
@ -238,15 +245,18 @@ static void on_write(void *tcpp, int from_iocp) {
} }
gpr_mu_unlock(&tcp->mu); gpr_mu_unlock(&tcp->mu);
GPR_ASSERT(tcp->socket->write_info.outstanding);
if (do_abort) { if (do_abort) {
if (from_iocp) gpr_slice_buffer_reset_and_unref(&tcp->write_slices); if (from_iocp) {
tcp->socket->write_info.outstanding = 0;
gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
}
tcp_unref(tcp); tcp_unref(tcp);
cb(opaque, GRPC_ENDPOINT_CB_SHUTDOWN); if (cb) cb(opaque, GRPC_ENDPOINT_CB_SHUTDOWN);
return; return;
} }
GPR_ASSERT(tcp->socket->write_info.outstanding);
if (info->wsa_error != 0) { if (info->wsa_error != 0) {
char *utf8_message = gpr_format_message(info->wsa_error); char *utf8_message = gpr_format_message(info->wsa_error);
gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
@ -361,11 +371,13 @@ static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
concurrent access of the data structure in that regard. */ concurrent access of the data structure in that regard. */
static void win_shutdown(grpc_endpoint *ep) { static void win_shutdown(grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *) ep; grpc_tcp *tcp = (grpc_tcp *) ep;
int extra_refs = 0;
gpr_mu_lock(&tcp->mu); gpr_mu_lock(&tcp->mu);
/* At that point, what may happen is that we're already inside the IOCP /* At that point, what may happen is that we're already inside the IOCP
callback. See the comments in on_read and on_write. */ callback. See the comments in on_read and on_write. */
tcp->shutting_down = 1; tcp->shutting_down = 1;
grpc_winsocket_shutdown(tcp->socket); extra_refs = grpc_winsocket_shutdown(tcp->socket);
while (extra_refs--) tcp_ref(tcp);
gpr_mu_unlock(&tcp->mu); gpr_mu_unlock(&tcp->mu);
} }

@ -32,7 +32,6 @@
<%namespace file="packages.include" import="get_openssl,get_zlib"/>\ <%namespace file="packages.include" import="get_openssl,get_zlib"/>\
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\ <%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<% <%
disallowed_dependencies = set(['end2end_certs'])
build_from_project_file = set(['gpr', build_from_project_file = set(['gpr',
'grpc', 'grpc',
'grpc_unsecure', 'grpc_unsecure',
@ -41,8 +40,7 @@
'grpc_test_util_unsecure', 'grpc_test_util_unsecure',
]) ])
buildable_targets = [ target for target in targets + libs buildable_targets = [ target for target in targets + libs
if not disallowed_dependencies.intersection(target.get('deps', [])) and if target.build in ['all', 'test', 'private', 'tool', 'benchmark'] and
target.build in ['all', 'test', 'private', 'tool', 'benchmark'] and
target.language in ['c', 'c++'] and target.language in ['c', 'c++'] and
all([src.endswith('.c') for src in target.src]) and all([src.endswith('.c') for src in target.src]) and
'windows' in target.get('platforms', ['windows']) ] 'windows' in target.get('platforms', ['windows']) ]
@ -136,6 +134,9 @@ $(LIBS) \
%for source in target.src: %for source in target.src:
$(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \ $(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \
%endfor %endfor
%if not target.src:
$(OUT_DIR)\dummy.obj \
%endif
%if target.build != 'private': %if target.build != 'private':
${target.name}: ${target.name}.exe ${target.name}: ${target.name}.exe

@ -4,12 +4,16 @@
<%def name="get_subsystem(is_library)">${'Windows' if is_library else 'Console'}</%def>\ <%def name="get_subsystem(is_library)">${'Windows' if is_library else 'Console'}</%def>\
<%def name="gen_project(name, collection, configuration_type = None, project_guid = None, props = [], packages = [])">\ <%def name="gen_project(name, collection, configuration_type = None, project_guid = None, props = [], packages = [])">\
<% <%
target = None
for p in vsprojects: for p in vsprojects:
if p.name == name: if p.name == name:
project = p project = p
for t in collection: for t in collection:
if t.name == name: if t.name == name:
target = t target = t
if not configuration_type and target:
if target.build == 'test' or target.build == 'tool':
configuration_type = 'Application'
if not configuration_type: if not configuration_type:
configuration_type = 'StaticLibrary' configuration_type = 'StaticLibrary'
if not project_guid: if not project_guid:

@ -107,6 +107,7 @@ class CLanguage(object):
plat = 'windows' plat = 'windows'
else: else:
plat = 'posix' plat = 'posix'
self.platform = plat
with open('tools/run_tests/tests.json') as f: with open('tools/run_tests/tests.json') as f:
js = json.load(f) js = json.load(f)
self.binaries = [tgt self.binaries = [tgt
@ -119,9 +120,12 @@ class CLanguage(object):
for target in self.binaries: for target in self.binaries:
if travis and target['flaky']: if travis and target['flaky']:
continue continue
if self.platform == 'windows':
binary = 'vsprojects\\test_bin\\%s.exe' % (target['name'])
else:
binary = 'bins/%s/%s' % (config.build_config, target['name']) binary = 'bins/%s/%s' % (config.build_config, target['name'])
out.append(config.job_spec([binary], [binary])) out.append(config.job_spec([binary], [binary]))
return out return sorted(out)
def make_targets(self): def make_targets(self):
return ['buildtests_%s' % self.make_target] return ['buildtests_%s' % self.make_target]

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save