Just compile the program and see for yourself. Then reset VECTOR_COUNT
to 16 and it works just fine.
% uname -a
Linux magic.highwind.com 2.2.5-15 #1 Mon Apr 19 23:00:46 EDT 1999 i686 unknown
I'm fairly sure this is in the latest kernel as well.
2. Although I do not have a test program for it, I am 100% sure that
even in the latest kernel, I sometimes see PARTIAL ::writev()'s of
data on blocking network connections.
Given that ::writev() on a blocking socket should never do
that, I suspect something isn't right in the networking code.
I wish this test program would show that problem,
unfortunately, it doesn't. However, I KNOW for a fact that I have seen
it. Perhaps some kind of signal logic interrupts writev(). I'm unsure.
In any case, ::writev() does sometimes perform a partial write
on a blocking socket, that is a BUG.
-Rob
------
/*****************************************************************************
File: writevTestLinux.C
Contents: writev() Bug Illustration
Created: 22-May-1999
Compile as:
g++ -Dlinux -D_REENTRANT -Wall -Werror -g -o writevTestLinux writevTestLinux.C -lpthread
Run as:
./writevTestLinux ip-address 9
(You run it against the "disgard" port (9) of a neighboring machine)
*****************************************************************************/
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <memory.h>
#include <netinet/in.h>
#if defined(linux)
#include <poll.h>
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#define VECTOR_COUNT UIO_MAXIOV
unsigned int threadCount = 10;
static void *writeThread(void *arg)
{
// Get the fd to writev() from the argument
int fd = *(static_cast<int *>(arg));
delete arg;
// We are going to write 1024 x's on each component of the vector
char buf[1024];
::memset(buf, 'x', 1024);
// Initialize the vector
iovec *iov = new iovec[VECTOR_COUNT];
for (int i = 0; i < VECTOR_COUNT; ++i) {
iov[i].iov_base = buf;
iov[i].iov_len = 1024;
}
::printf("Starting writev() Loop.\n");
for (int x = 0; x < 10; ++x) {
int written = ::writev(fd, iov, VECTOR_COUNT);
// Because this is a BLOCKING "writev()" there are only 2
// valid return values:
// -1 == Some kind of error
// 1024 * VECTOR_COUNT == Success on writing everything
//
// ANY other return value indicates something is BROKEN!!!!
if (written == -1) {
::printf("::writev() returned an error! (%d)\n", errno);
delete [] iov;
return 0;
}
if (written != 1024 * VECTOR_COUNT) {
::printf("::writev() is SERIOUSLY BROKEN.\n"
"A blocking ::writev() of %d bytes returned %d bytes\n",
1024 * VECTOR_COUNT, written);
delete [] iov;
return 0;
}
}
::printf("Finished writev() Loop.\n");
delete [] iov;
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
::printf("Run as %s ip-address port\n", argv[0]);
return EXIT_FAILURE;
}
::printf("Test Starting\n");
// Initialize network data structure
int fd = -1;
sockaddr_in location;
::memset(&location, 0, sizeof(location));
location.sin_family = AF_INET;
location.sin_addr.s_addr = ::inet_addr(argv[1]);
location.sin_port = htons(::strtoul(argv[2], 0, 10));
for (unsigned int k = 0; k < threadCount; ++k) {
// Connect to the target
assert((fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1);
assert(::connect(fd, reinterpret_cast<sockaddr *>(&location),
sizeof(location)) != -1);
// Do one NON-threaded call just as a test
writeThread(new int(fd));
// Initialize Thread Attributes
pthread_t tid;
pthread_attr_t attr;
assert(!::pthread_attr_init(&attr));
assert(!::pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED));
assert(!::pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM));
// Spawn the thread
assert(!::pthread_create(&tid, &attr, writeThread,
new int(fd)));
// Cleanup Thread Attributes
assert(!::pthread_attr_destroy(&attr));
}
// Just sleep for 15 seconds.
::printf("Waiting for Threads\n");
::poll(0, 0, 15 * 1000);
::printf("Test Exiting\n");
return EXIT_SUCCESS;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/