|
|
@ -146,61 +146,57 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { |
|
|
|
grpc_timer_cancel(exec_ctx, &ac->alarm); |
|
|
|
grpc_timer_cancel(exec_ctx, &ac->alarm); |
|
|
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&ac->mu); |
|
|
|
gpr_mu_lock(&ac->mu); |
|
|
|
if (error == GRPC_ERROR_NONE) { |
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
do { |
|
|
|
|
|
|
|
so_error_size = sizeof(so_error); |
|
|
|
|
|
|
|
err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, |
|
|
|
|
|
|
|
&so_error_size); |
|
|
|
|
|
|
|
} while (err < 0 && errno == EINTR); |
|
|
|
|
|
|
|
if (err < 0) { |
|
|
|
|
|
|
|
error = GRPC_OS_ERROR(errno, "getsockopt"); |
|
|
|
|
|
|
|
goto finish; |
|
|
|
|
|
|
|
} else if (so_error != 0) { |
|
|
|
|
|
|
|
if (so_error == ENOBUFS) { |
|
|
|
|
|
|
|
/* We will get one of these errors if we have run out of
|
|
|
|
|
|
|
|
memory in the kernel for the data structures allocated |
|
|
|
|
|
|
|
when you connect a socket. If this happens it is very |
|
|
|
|
|
|
|
likely that if we wait a little bit then try again the |
|
|
|
|
|
|
|
connection will work (since other programs or this |
|
|
|
|
|
|
|
program will close their network connections and free up |
|
|
|
|
|
|
|
memory). This does _not_ indicate that there is anything |
|
|
|
|
|
|
|
wrong with the server we are connecting to, this is a |
|
|
|
|
|
|
|
local problem. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If you are looking at this code, then chances are that |
|
|
|
|
|
|
|
your program or another program on the same computer |
|
|
|
|
|
|
|
opened too many network connections. The "easy" fix: |
|
|
|
|
|
|
|
don't do that! */ |
|
|
|
|
|
|
|
gpr_log(GPR_ERROR, "kernel out of buffers"); |
|
|
|
|
|
|
|
gpr_mu_unlock(&ac->mu); |
|
|
|
|
|
|
|
grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
switch (so_error) { |
|
|
|
|
|
|
|
case ECONNREFUSED: |
|
|
|
|
|
|
|
error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errno); |
|
|
|
|
|
|
|
error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, |
|
|
|
|
|
|
|
"Connection refused"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
error = GRPC_OS_ERROR(errno, "getsockopt(SO_ERROR)"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
goto finish; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); |
|
|
|
|
|
|
|
*ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str); |
|
|
|
|
|
|
|
fd = NULL; |
|
|
|
|
|
|
|
goto finish; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
error = |
|
|
|
error = |
|
|
|
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred"); |
|
|
|
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred"); |
|
|
|
goto finish; |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GPR_UNREACHABLE_CODE(return ); |
|
|
|
do { |
|
|
|
|
|
|
|
so_error_size = sizeof(so_error); |
|
|
|
|
|
|
|
err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, |
|
|
|
|
|
|
|
&so_error_size); |
|
|
|
|
|
|
|
} while (err < 0 && errno == EINTR); |
|
|
|
|
|
|
|
if (err < 0) { |
|
|
|
|
|
|
|
error = GRPC_OS_ERROR(errno, "getsockopt"); |
|
|
|
|
|
|
|
goto finish; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (so_error) { |
|
|
|
|
|
|
|
case 0: |
|
|
|
|
|
|
|
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); |
|
|
|
|
|
|
|
*ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str); |
|
|
|
|
|
|
|
fd = NULL; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ENOBUFS: |
|
|
|
|
|
|
|
/* We will get one of these errors if we have run out of
|
|
|
|
|
|
|
|
memory in the kernel for the data structures allocated |
|
|
|
|
|
|
|
when you connect a socket. If this happens it is very |
|
|
|
|
|
|
|
likely that if we wait a little bit then try again the |
|
|
|
|
|
|
|
connection will work (since other programs or this |
|
|
|
|
|
|
|
program will close their network connections and free up |
|
|
|
|
|
|
|
memory). This does _not_ indicate that there is anything |
|
|
|
|
|
|
|
wrong with the server we are connecting to, this is a |
|
|
|
|
|
|
|
local problem. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If you are looking at this code, then chances are that |
|
|
|
|
|
|
|
your program or another program on the same computer |
|
|
|
|
|
|
|
opened too many network connections. The "easy" fix: |
|
|
|
|
|
|
|
don't do that! */ |
|
|
|
|
|
|
|
gpr_log(GPR_ERROR, "kernel out of buffers"); |
|
|
|
|
|
|
|
gpr_mu_unlock(&ac->mu); |
|
|
|
|
|
|
|
grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
case ECONNREFUSED: |
|
|
|
|
|
|
|
/* This error shouldn't happen for anything other than connect(). */ |
|
|
|
|
|
|
|
error = GRPC_OS_ERROR(so_error, "connect"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
/* We don't really know which syscall triggered the problem here,
|
|
|
|
|
|
|
|
so punt by reporting getsockopt(). */ |
|
|
|
|
|
|
|
error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
finish: |
|
|
|
finish: |
|
|
|
if (fd != NULL) { |
|
|
|
if (fd != NULL) { |
|
|
|