Most recent kernel where this bug did not occur: Distribution: Debian Hardware Environment: various x86 Software Environment: Tested under various versions of Debian GNU/Linux Problem Description: If there is some unread data in a socket and some data has been sent with the MSG_MORE flag and the socket is closed, the MSG_MORE sent data isn't sent. Steps to reproduce: Compile this program, start it with a free TCP-port number and connect to that port with telnet. Send 2 or more characters. The result should be "HI THERE\r\n", but becomes "HI " on kernels with the bug. -----------------------------8<--------------------------- #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <netdb.h> #include <string.h> int main(int argc, char **argv) { struct sockaddr_in socket_addr; int fd = socket(PF_INET, SOCK_STREAM, 0); socklen_t len = sizeof(socket_addr); int on = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); memset(&socket_addr, 0, sizeof(socket_addr)); socket_addr.sin_family = AF_INET; socket_addr.sin_port = htons(atoi(argv[1])); socket_addr.sin_addr.s_addr = INADDR_ANY; bind(fd, (struct sockaddr *) &socket_addr, sizeof(socket_addr)); listen(fd, 1); fd = accept(fd, (struct sockaddr *) &socket_addr, &len); recv(fd, &on, 1, 0); send(fd, "HI ", 3, 0); send(fd, "THERE\r\n", 7, MSG_MORE); close(fd); sleep(5); return 0; } -----------------------------8<---------------------------
Begin forwarded message: Date: Fri, 14 Oct 2005 02:37:55 -0700 From: bugme-daemon@kernel-bugs.osdl.org To: bugme-new@lists.osdl.org Subject: [Bugme-new] [Bug 5437] New: Sending with MSG_MORE causes data-loss. http://bugzilla.kernel.org/show_bug.cgi?id=5437 Summary: Sending with MSG_MORE causes data-loss. Kernel Version: 2.6.11 Status: NEW Severity: normal Owner: shemminger@osdl.org Submitter: bofh-reg-kernel-bug@diegeekdie.com Most recent kernel where this bug did not occur: Distribution: Debian Hardware Environment: various x86 Software Environment: Tested under various versions of Debian GNU/Linux Problem Description: If there is some unread data in a socket and some data has been sent with the MSG_MORE flag and the socket is closed, the MSG_MORE sent data isn't sent. Steps to reproduce: Compile this program, start it with a free TCP-port number and connect to that port with telnet. Send 2 or more characters. The result should be "HI THERE\r\n", but becomes "HI " on kernels with the bug. -----------------------------8<--------------------------- #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <netdb.h> #include <string.h> int main(int argc, char **argv) { struct sockaddr_in socket_addr; int fd = socket(PF_INET, SOCK_STREAM, 0); socklen_t len = sizeof(socket_addr); int on = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); memset(&socket_addr, 0, sizeof(socket_addr)); socket_addr.sin_family = AF_INET; socket_addr.sin_port = htons(atoi(argv[1])); socket_addr.sin_addr.s_addr = INADDR_ANY; bind(fd, (struct sockaddr *) &socket_addr, sizeof(socket_addr)); listen(fd, 1); fd = accept(fd, (struct sockaddr *) &socket_addr, &len); recv(fd, &on, 1, 0); send(fd, "HI ", 3, 0); send(fd, "THERE\r\n", 7, MSG_MORE); close(fd); sleep(5); return 0; } -----------------------------8<--------------------------- ------- You are receiving this mail because: ------- You are on the CC list for the bug, or are watching someone who is.
Andrew Morton <akpm@osdl.org> wrote: > > If there is some unread data in a socket and some data has been sent with the > MSG_MORE flag and the socket is closed, the MSG_MORE sent data isn't sent. IMHO this is correct behaviour (although there may be a separate bug in TCP, see below). First of all MSG_MORE is a Linux-specific feature so we're not bound by any standards. More importantly, it makes sense to discard the data here. The reason is that MSG_MORE is telling the kernel to not send the data straight away because you *will* make another send call later on to trigger the transmission. As you closed the socket without making another send call (or an ioctl to the same effect), it would seem reasonable for the kernel to interpret that as a desire to discard the data. In fact, this behaviour is entirely consistent with the manual page entry in send(2) about MSG_MORE: MSG_MORE (Since Linux 2.4.4) The caller has more data to send. This flag is used with TCP sockets to obtain the same effect as the TCP_CORK socket option (see tcp(7)), with the difference that this flag can be set on a per-call basis. Since Linux 2.6, this flag is also supported for UDP sockets, and informs the kernel to package all of the data sent in calls with this flag set into a single datagram which is only transmitted when a call is performed that does not specify this flag. If you want to send the data as is you could execute an ioctl to uncork the socket. Alternatively, you should be able to do an empty send(2) with MSG_MORE cleared to push the pending data out. Actually, TCP seems to ignore an empty send(2) without MSG_MORE even if there is pending data. This looks like a bug to me. Dave? Cheers,
If there is nothing to be read (connect to the testprogram's port with telnet and just press ctrl-d), then all data will be sent to the client. So it is not consistent from a servers point of view. I think most people would expect MSG_MORE sent data to actually be sent without having to perform an extra syscall before a close. At least I view MSG_MORE as a performance increasing function (like TCP_CORK, but without having to add more syscalls), not as a way to be able to avoid sending data before a close. Adding an extra syscall before close to flush out MSG_MORE data lowers that performance somewhat. I've not looked at the server code, but since the Nagle algorithm already may have some data buffered-to-be-sent, I would suspect that it would be almost costless to also check for MSG_MORE/CORKED data at closing time.
In article <E1EQOnG-0006O6-00@gondolin.me.apana.org.au> (at Fri, 14 Oct 2005 22:36:14 +1000), Herbert Xu <herbert@gondor.apana.org.au> says: > Andrew Morton <akpm@osdl.org> wrote: > > > > If there is some unread data in a socket and some data has been sent with > the > > MSG_MORE flag and the socket is closed, the MSG_MORE sent data isn't sent. > > IMHO this is correct behaviour (although there may be a separate bug > in TCP, see below). : > More importantly, it makes sense to discard the data here. The reason > is that MSG_MORE is telling the kernel to not send the data straight > away because you *will* make another send call later on to trigger the > transmission. > > As you closed the socket without making another send call (or an ioctl > to the same effect), it would seem reasonable for the kernel to interpret > that as a desire to discard the data. I second this. I don't think current behavior is buggy. --yoshfuji
Reply-To: dada1@cosmosbay.com Andrew Morton a
Reply-To: davem@davemloft.net From: YOSHIFUJI Hideaki / $B5HF#1QL@(B <yoshfuji@linux-ipv6.org> Date: Fri, 14 Oct 2005 22:24:28 +0900 (JST) > I second this. I don't think current behavior is buggy. I also agree. All we've shown is that the test program is buggy :-) To answer Herbert's other query, I think it is wrong to handle a zero length non-MSG_MORE request after MSG_MORE. The user should clear MSG_MORE when there is in fact no more data to send. So in essence, "NOTABUG", and let's move on :-)