Prevent SIGPIPE from terminating embedded STCP transports
This commit is contained in:
1 parent
11aa760d47
commit
fdcf92be04
3 files changed
+29
-2
No files matched your search
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "socket_compat.h"
|
||||
#include "debug_config.h"
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// ==================== Windows Implementation ====================
|
||||
@@ -211,6 +212,27 @@ int socket_set_mark(socket_t sock, int mark) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Ошибки send остаются у вызывающего; закрытый пир не завершает процесс сигналом. */
|
||||
ssize_t socket_send(socket_t sock, const void* buf, size_t len) {
|
||||
#ifdef _WIN32
|
||||
if (len > INT_MAX) { WSASetLastError(WSAEMSGSIZE); return SOCKET_ERROR_CODE; }
|
||||
return send(sock, (const char*)buf, (int)len, 0);
|
||||
#elif defined(MSG_NOSIGNAL)
|
||||
return send(sock, buf, len, MSG_NOSIGNAL);
|
||||
#elif defined(SO_NOSIGPIPE)
|
||||
int enabled = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &enabled, sizeof(enabled)) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "cannot disable SIGPIPE for socket=%d: %s", (int)sock, strerror(errno));
|
||||
return SOCKET_ERROR_CODE;
|
||||
}
|
||||
return send(sock, buf, len, 0);
|
||||
#else
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "safe TCP send is unsupported on this platform");
|
||||
errno = ENOTSUP;
|
||||
return SOCKET_ERROR_CODE;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t socket_sendto(socket_t sock, const void* buf, size_t len,
|
||||
const struct sockaddr* dest, socklen_t dest_len) {
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -75,6 +75,11 @@ int socket_bind_to_device(socket_t sock, const char* ifname);
|
||||
// SO_MARK в значение mark; 0 / -1. Без поддержки опции, в том числе Windows, возвращает -1.
|
||||
int socket_set_mark(socket_t sock, int mark);
|
||||
|
||||
/* Один TCP send без SIGPIPE и изменения обработчиков процесса. Буфер заимствован;
|
||||
* возвращает число байт либо SOCKET_ERROR_CODE, включая EAGAIN. Ошибку логирует владелец.
|
||||
* MSG_NOSIGNAL либо SO_NOSIGPIPE; без поддержки возвращает ENOTSUP. Windows: len <= INT_MAX. */
|
||||
ssize_t socket_send(socket_t sock, const void* buf, size_t len);
|
||||
|
||||
// Один sendto/recvfrom с flags=0: число байт или SOCKET_ERROR_CODE; errno/WSA-код читать через socket_get_error.
|
||||
// буферами владеет вызывающий; для Windows len должен помещаться в int. dest_len — размер адреса назначения;
|
||||
// src_len при приёме — входная ёмкость/выходная длина адреса (может быть NULL по правилам recvfrom ОС).
|
||||
|
||||
@@ -186,7 +186,7 @@ int stcp_send_raw(struct stcp_conn *c, uint8_t *data, size_t len) {
|
||||
c->wire_bytes += len;
|
||||
return 1;
|
||||
}
|
||||
ssize_t sent = send(c->sock, data, len, 0);
|
||||
ssize_t sent = socket_send(c->sock, data, len);
|
||||
if (sent < 0) {
|
||||
int err = socket_get_error();
|
||||
if (err != ERR_AGAIN && err != ERR_WOULDBLOCK) {
|
||||
@@ -234,7 +234,7 @@ void stcp_write_cb(socket_t sock, void *arg) {
|
||||
struct stcp_conn *c = (struct stcp_conn *)arg;
|
||||
if (c->close_err) { if (!c->close_call_soon) stcp_conn_do_close(c, c->close_err); return; }
|
||||
if (!c->send_buf) { uasync_set_socket_write(c->ua, c->socket_id, 0); return; }
|
||||
ssize_t sent = send(sock, c->send_buf + c->send_offset, c->send_len - c->send_offset, 0);
|
||||
ssize_t sent = socket_send(sock, c->send_buf + c->send_offset, c->send_len - c->send_offset);
|
||||
if (sent < 0) {
|
||||
int err = socket_get_error();
|
||||
if (err == ERR_AGAIN || err == ERR_WOULDBLOCK) return;
|
||||
|
||||
Reference in new issue
Block a user