From 86e596b8709e79322a6fcf20637766ba6e3c2cdc Mon Sep 17 00:00:00 2001 From: leitner Date: Thu, 22 Apr 2021 12:53:53 +0000 Subject: [PATCH] limit iovec size for sendmsg code path to 50 --- io/iob_send.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/io/iob_send.c b/io/iob_send.c index ad13f09..68018f1 100644 --- a/io/iob_send.c +++ b/io/iob_send.c @@ -128,8 +128,8 @@ int64 iob_send(int64 s,io_batch* b) { struct iovec* v; uint64 total; int64 sent; - long i; - long headers; + size_t i; + size_t headers; #ifdef MSG_MORE int docork; #endif @@ -255,7 +255,42 @@ eagain: memset(&msg,0,sizeof(msg)); msg.msg_iov=v; msg.msg_iovlen=headers; - sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY); + /* Difficulty: sendmsg has a built-in limit on the cmsgdata on + * Linux, net.core.optmem_max with a 20k default size. So we + * need to do a little song and dance here to not trigger it */ + if (headers > 50) { + size_t skip=0, totalsent=0; + for (skip=0; skip 50) n=50; + for (i=0; i 0) totalsent += sent; + if (sent == l) continue; // we sent as much as we wanted, go for next batch + if (sent >= 0) { // we wrote something but not the whole batch + sent = totalsent; + break; + } + // we got an error, maybe EAGAIN + if (errno==EAGAIN) { + if (totalsent == 0) { + io_eagain_write(s); + return -1; + } + sent = totalsent; + // fall through + } + // actual error + break; + } + // if we get here, we wrote it all + sent = totalsent; + } else + sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY); } } if (sent==-1) {