|
|
|
@ -546,6 +546,19 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number
|
|
|
|
|
* of bytes sent. */ |
|
|
|
|
ssize_t tcp_send(int fd, const struct msghdr* msg) { |
|
|
|
|
GPR_TIMER_SCOPE("sendmsg", 1); |
|
|
|
|
ssize_t sent_length; |
|
|
|
|
do { |
|
|
|
|
/* TODO(klempner): Cork if this is a partial write */ |
|
|
|
|
GRPC_STATS_INC_SYSCALL_WRITE(); |
|
|
|
|
sent_length = sendmsg(fd, msg, SENDMSG_FLAGS); |
|
|
|
|
} while (sent_length < 0 && errno == EINTR); |
|
|
|
|
return sent_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** This is to be called if outgoing_buffer_arg is not null. On linux platforms,
|
|
|
|
|
* this will call sendmsg with socket options set to collect timestamps inside |
|
|
|
|
* the kernel. On return, sent_length is set to the return value of the sendmsg |
|
|
|
@ -575,7 +588,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
tcp->bytes_counter = 0; |
|
|
|
|
tcp->bytes_counter = -1; |
|
|
|
|
tcp->socket_ts_enabled = true; |
|
|
|
|
} |
|
|
|
|
/* Set control message to indicate that you want timestamps. */ |
|
|
|
@ -593,7 +606,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, |
|
|
|
|
msg->msg_controllen = CMSG_SPACE(sizeof(uint32_t)); |
|
|
|
|
|
|
|
|
|
/* If there was an error on sendmsg the logic in tcp_flush will handle it. */ |
|
|
|
|
ssize_t length = sendmsg_wrapper(tcp->fd, msg); |
|
|
|
|
ssize_t length = tcp_send(tcp->fd, msg); |
|
|
|
|
*sent_length = length; |
|
|
|
|
/* Only save timestamps if all the bytes were taken by sendmsg. */ |
|
|
|
|
if (sending_length == static_cast<size_t>(length)) { |
|
|
|
@ -761,19 +774,6 @@ static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { |
|
|
|
|
} |
|
|
|
|
#endif /* GRPC_LINUX_ERRQUEUE */ |
|
|
|
|
|
|
|
|
|
/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number
|
|
|
|
|
* of bytes sent. */ |
|
|
|
|
ssize_t sendmsg_wrapper(int fd, const struct msghdr* msg) { |
|
|
|
|
GPR_TIMER_SCOPE("sendmsg", 1); |
|
|
|
|
ssize_t sent_length; |
|
|
|
|
do { |
|
|
|
|
/* TODO(klempner): Cork if this is a partial write */ |
|
|
|
|
GRPC_STATS_INC_SYSCALL_WRITE(); |
|
|
|
|
sent_length = sendmsg(fd, msg, SENDMSG_FLAGS); |
|
|
|
|
} while (sent_length < 0 && errno == EINTR); |
|
|
|
|
return sent_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* returns true if done, false if pending; if returning true, *error is set */ |
|
|
|
|
#if defined(IOV_MAX) && IOV_MAX < 1000 |
|
|
|
|
#define MAX_WRITE_IOVEC IOV_MAX |
|
|
|
@ -830,7 +830,7 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { |
|
|
|
|
GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); |
|
|
|
|
GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); |
|
|
|
|
|
|
|
|
|
sent_length = sendmsg_wrapper(tcp->fd, &msg); |
|
|
|
|
sent_length = tcp_send(tcp->fd, &msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (sent_length < 0) { |
|
|
|
|