-
Questions about pthreads
Hey, I am starting to mess around with the libpthreads implementation on GNU/Linux. I do not understand why for instance, when I use pthread_create() to create threads, sometimes, no threads are created. To even see any output from threads whatsoever I have to literally create hundreds of threads. No matter how many I create, there always seems to be an inconsistent amount being created. Here is some of my code that demonstrates these problems I am having.
Code:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
void usage(char *);
void *net_thread(void *);
FILE *glob_file;
int glob_port;
int main(int argc, char *argv[])
{
int numthreads, rc;
long i;
srand(time(NULL));
if(argc != 4)
usage(argv[0]);
glob_port = atoi(argv[1]);
numthreads = atoi(argv[2]);
unsigned long *taskids[numthreads];
pthread_t thread_array[numthreads];
glob_file = fopen(argv[3], "w+");
// generate array of random ip addresses
for(i = 0; i <= numthreads; i++)
{
taskids[i] = (long *) malloc(sizeof(long));
*taskids[i] = i;
rc = pthread_create(&thread_array[i], NULL, net_thread, (void *) taskids[i]);
}
return 0;
}
void usage(char *progname)
{
fprintf(stderr, "Usage: %s <port> <numthread> <output file>\n", progname);
exit(1);
}
void *net_thread(void *thr_arg)
{
int sockfd;
unsigned long connip;
unsigned int a, b, c, d;
struct sockaddr_in mysock;
char str_ip[30];
connip = (rand()) * (long) (thr_arg);
// separate bytes in connip
a = (connip >> 24 & 0xFF);
b = (connip >> 16 & 0xFF);
c = (connip >> 8 & 0xFF);
d = (connip & 0xFF);
printf("from thread: %X\tdotted notation: %d.%d.%d.%d\n", connip, a, b, c, d);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
pthread_exit(NULL);
}
snprintf(str_ip, sizeof(str_ip), "%d.%d.%d.%d", a, b, c, d);
bzero(&mysock, sizeof(mysock));
mysock.sin_family = AF_INET;
mysock.sin_port = htons(glob_port); // short, network byte order
mysock.sin_addr.s_addr = htonl(connip);
if((connect(sockfd, (struct sockaddr *) &mysock, sizeof(mysock))) == -1){
switch(errno){
case ECONNREFUSED:
fprintf(glob_file, "Port %d Closed on %s\n", glob_port, str_ip);
break;
default:
break;
}
pthread_exit(NULL);
}
/* connection succeeds */
else{
fprintf(glob_file, "Port %d Open on %s\n", glob_port, str_ip);
pthread_exit(NULL);
}
pthread_exit(NULL);
}
-
You should really clean up that code example. There are no newline showing at all.
-
Sorry about that, it had something t do with chromium.
-
Use pthread_join at the end of main to join on all the threads you have created (basicly wait for them to all finish before you exit the main application since this will cause the threads to stop aswell if my memory serves me right). Use fflush(stdout) to flush the output buffer to the screen after each printf (this will probably cause mumbled printing to the screen, use a mutex around printf statements if you want to get rid of that) (if you dont want the fprintf to cause mumbled writing you should probably protect those writes with a mutex, oh and make sure you flush glob_file aswell)
Code:
if((connect(sockfd, (struct sockaddr *) &mysock, sizeof(mysock))) == -1){
switch(errno){
case ECONNREFUSED:
fprintf(glob_file, "Port %d Closed on %s\n", glob_port, str_ip);
break;
default:
break;
}
pthread_exit(NULL);
}
/* connection succeeds */
else{
fprintf(glob_file, "Port %d Open on %s\n", glob_port, str_ip);
pthread_exit(NULL);
}
pthread_exit(NULL);
These pthread_exit calls are all unnecessary (an implicit pthread_exit is called when you return from the start routine...just need a return value)