I am begining with the pthread library and I would like to execute a function like this several time in parallel :
while(true) {
//Part A
//do several stuff
//End of Part A
//Part B
//do other stuffs
//End of Part B
}
I can do that easily by lopping on pthread_create(). The problem is that the main program seems to switch thread before the part B is executed. As a result I see part A executed over and over but never part B. Could someone help?
Some actual code =>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#define error(msg) \
perror(msg); \
exit(EXIT_FAILURE)
//Declarations
int mastersocket;
struct sockaddr_in addr;
struct hostent *fromhost, *tohost;
int nthread=5;
int decdomain=13;
long serveurdns=0x0101a8c0;
static void * test(void * p_data) {
while(1) {
printf("hello\n");
}
return NULL;
}
int main(int argc, char **argv) {
int k, l;
pthread_t idt[5];
//Assignation, mallocs
//Strings
//Appel a socket
if( (mastersocket=socket(PF_INET, SOCK_DGRAM, 0)) < 0 ) {
error("socket");
}
//Configuration de sockaddr pour l'appel a bind
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(53);
//Appel a bind
if( (bind(mastersocket, (struct sockaddr *)&addr, sizeof(addr))) < 0 ) {
error("bind");
}
for(k=0; k<nthread; k++) {
pthread_create(&idt[k], NULL, mainbis, (void *)mastersocket);
}
mainbis((void *)mastersocket);
return 0;
}
static void * mainbis(void * p_data) {
int socketh= (int) p_data;
int found=0, len, cc;
char *buf, *curfish;
struct sockaddr_in *from, *to;
u_long fromaddr, toaddr;
int lenbuf=5000;
buf=(char *)malloc(lenbuf);
curfish=(char *)malloc(100);
len=sizeof(struct sockaddr_in);
to=(struct sockaddr_in *)malloc(len);
from=(struct sockaddr_in *)malloc(len);
//Structure sockaddr du serveur DNS vers lequel on redirige les requete
to->sin_family=AF_INET;
to->sin_addr.s_addr=serveurdns;
to->sin_port=htons(53);
//Let's go
while(1) {
found=0;
curfish=NULL;
//Reception des requetes
if((cc=recvfrom(socketh, buf, lenbuf, 0, (struct sockaddr *)from, &len))<0) {
error("recv");
}
buf[cc]='\0';
//Identification de l'host appelant
//fromaddr=(*from).sin_addr.s_addr;
//fromhost=gethostbyaddr((void *)&fromaddr, sizeof(fromaddr), AF_INET);
//Sortie utilisateur
printf("\n\n-- New Request From $$ on Port ... Domain = %s ||\n-- ***********************\n", buf+13);
curfish=somefunction();
if( curfish!=NULL ) {
found=1;
}
if(sendto(socketh, buf, cc, 0, (struct sockaddr *)to, len)<0) {
error("send");
}
if((cc=recvfrom(socketh, buf, lenbuf, 0, (struct sockaddr *)to, &len))<0) {
error("recv");
}
buf[cc]='\0';
printf("\n\n-- New Response From $$ on Port ||\n-- ***********************\n");
if(found) {
buf[cc-1]=0x81;
buf[cc-2]=0x2;
buf[cc-3]=0xa8;
buf[cc-4]=0xc0;
}
if(sendto(socketh, buf, cc, 0, (struct sockaddr *)from, len)<0) {
error("send");
}
}
return NULL;
}
It’s a UDP redirector for DNS request, when I launch and try to use dig for instance, my program always output the “New Request…” string but never the “New Response…” one and dig never get the response.
Jules
Your code can’t work. You bind 1 socket
mastersocket, and you create several threads using this socket.This is by itself ok, but the logic inside mainbis() assumes that it will read a reply to what it sent.
That might not happen, the reply could be read by any of the other threads you create that is blocking in
recvfromon that same socket, and the logic falls apart.Create a new socket in each thread that it uses to communicate with the real dns server, and only use
sockethto communicate with the clients.