diff --git a/src/box/iproto.cc b/src/box/iproto.cc index 45a6d1bf1ce067b181118cb92972acc39de83d91..e50461ad5c4dfc45e7614e104ea079c7d86e0d8f 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -266,6 +266,26 @@ iproto_connection_stop(struct iproto_connection *con) rlist_add_tail(&stopped_connections, &con->in_stop_list); } +/** + * Try to write an iproto error to a socket in the blocking mode. + * It is useful, when a connection is going to be closed and it is + * neccessary to response any error information to the user before + * closing. + * @param sock Socket to write to. + * @param error Error to write. + */ +static inline void +iproto_write_error_blocking(int sock, const struct error *e) +{ + /* Set to blocking to write the error. */ + int flags = fcntl(sock, F_GETFL, 0); + if (flags < 0) + return; + (void) fcntl(sock, F_SETFL, flags & (~O_NONBLOCK)); + iproto_write_error(sock, e, ::schema_version); + (void) fcntl(sock, F_SETFL, flags); +} + static void iproto_connection_on_input(ev_loop * /* loop */, struct ev_io *watcher, int /* revents */); @@ -773,7 +793,7 @@ iproto_connection_on_input(ev_loop *loop, struct ev_io *watcher, iproto_enqueue_batch(con, in); } catch (Exception *e) { /* Best effort at sending the error message to the client. */ - iproto_write_error(fd, e, ::schema_version); + iproto_write_error_blocking(fd, e); e->log(); iproto_connection_close(con); } diff --git a/src/box/xrow.c b/src/box/xrow.c index 1d24097b17963f8cae5a1a0f6cbcbf10ffeac90f..f3f42dd7e7e2cadfe557316988cf41a4fdcc471c 100644 --- a/src/box/xrow.c +++ b/src/box/xrow.c @@ -30,7 +30,6 @@ */ #include "xrow.h" -#include <fcntl.h> #include <msgpuck.h> #include <small/region.h> #include <small/obuf.h> @@ -301,20 +300,9 @@ iproto_write_error(int fd, const struct error *e, uint32_t schema_version) schema_version, sizeof(body) + msg_len); body.v_data_len = mp_bswap_u32(msg_len); - - /* Set to blocking to write the error. */ - int flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - return; - - (void) fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - size_t r = write(fd, header, sizeof(header)); - r = write(fd, &body, sizeof(body)); - r = write(fd, e->errmsg, msg_len); - (void) r; - - (void) fcntl(fd, F_SETFL, flags); + (void) write(fd, header, sizeof(header)); + (void) write(fd, &body, sizeof(body)); + (void) write(fd, e->errmsg, msg_len); } enum { SVP_SIZE = IPROTO_HEADER_LEN + sizeof(iproto_body_bin) };