[TESTCASE] Re: panic when invoking recvfrom
[TESTCASE] Re: panic when invoking recvfrom
- Subject: [TESTCASE] Re: panic when invoking recvfrom
- From: Peter Kirk <email@hidden>
- Date: Fri, 27 Jul 2007 14:51:40 +0200
On Thursday 05 July 2007 16:31, Peter Kirk wrote:
> Now, my application is closed-source, I cannot post it, and I tried to
> produce a test-case and failed at it (recvfrom didn't ever cause a kernel
> panic, although I was sending/receiving many thousands of UDP packets with
> the test-app).
Hi list,
finally I have been able to produce a test-case, which is attached (96 lines
of C-Code). To reproduce compile like:
gcc -Wall nettestcase.c -lpthread -o nettestcase
and then run
./nettestcase
In the few tests I did with this testcase the kernel panic occurred within a
few seconds. If all is well the application shouldn't ever terminate, but
keep reporting messages like "received 47700".
Short description of the code:
I use pthreads to spawn two threads which run through select(), recvfrom()
cycles, while the "main thread" runs in a loop sending packets at ourselves
for the two slaves threads to receive. The kernel panic can be avoided by
just having one thread in the select(), recvfrom() cycle, just adjust
NUM_THREADS in line 12 to "1" instead of "2" to see what I mean.
If required the sending and the receiving parts could be put into two
different programmes, so that the sending part could be run on a different
computer, which would further demonstrate that only the receiving part plays
a part in the panic. Please let me know if you require me to do this split,
it should be fairly trivial (but unnecessary in my opinion).
Peter
--
Brain damage is all in your head.
-- Karl Lehenbauer
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#define NUM_THREADS 2
void* threadSpawnRecv(void* args);
int selectThenRecvFrom();
int sendData();
int sock;
int main() {
struct sockaddr_in addr;
pthread_t threads[NUM_THREADS];
int i;
//create a new socket
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock < 0 ) {
printf("socket() failed\n");
return -1;
}
addr.sin_family = AF_INET;
if( (addr.sin_addr.s_addr = inet_addr("0.0.0.0")) == INADDR_NONE) {
printf("converting bind() IP failed\n");
return -1;
}
addr.sin_port = htons(1337);
if(bind(sock, (struct sockaddr*) &addr, sizeof(addr) ) < 0 ) {
printf("converting bind() IP failed %s\n", strerror(errno));
return -1;
}
for(i = 0; i < NUM_THREADS; ++i) {
if(pthread_create(&threads[i], NULL, threadSpawnRecv, NULL) != 0) {
return -1;
}
}
while(sendData() == 0) {} //send data in a loop
return 0;
}
void* threadSpawnRecv(void* args) { //try to receive data in a loop
while(selectThenRecvFrom() == 0) {}
exit(-1); //if any of the receiver threads exists out we terminate the programme
}
int selectThenRecvFrom() { //check to see if there is data avaliable at the socket via select, and use recvfrom if there is to receive it
static int count = 0;
fd_set readSet; //build new set
FD_ZERO(&readSet);
FD_SET(sock, &readSet); //adds the socket to our readSet
struct timeval selectTimeout;
selectTimeout.tv_sec = 0;
selectTimeout.tv_usec = 10000;
if (select(sock + 1, &readSet, NULL, NULL, &selectTimeout) < 0) { //select to find if sock has new data
printf("select() failed, %s\n", strerror(errno));
return -1;
}
if(FD_ISSET(sock, &readSet)) {
unsigned char buffer[4*1024];
struct sockaddr from;
socklen_t fromLen = sizeof(from);
if (recvfrom(sock, buffer, sizeof(buffer), MSG_DONTWAIT, &from, &fromLen) < 0) { //receive data
//printf("Failed during recvfrom, %s\n", strerror(errno));
return 0; //try again
}
if(++count % 100 == 0) printf("received %d\n", count);
}
return 0;
}
int sendData() { //send one packet of data to ourself
struct sockaddr_in m_sendto;
m_sendto.sin_family = AF_INET;
if((m_sendto.sin_addr.s_addr = inet_addr("127.0.0.1")) == INADDR_NONE) {
printf("Failed to convert sendto IP\n");
return -1;
}
m_sendto.sin_port = htons(1337);
int tolen = sizeof(m_sendto);
if(sendto(sock, "1234567890", 10, 0, (struct sockaddr*)&m_sendto, tolen) == -1) {
printf("Failed to \'sendto\': %s\n", strerror(errno));
return -1;
}
return 0;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden