Thread: Need help with running multiple theads

  1. #1
    Registered User
    Join Date
    May 2016
    Posts
    31

    Need help with running multiple theads

    So I made a proxy tester. It sends a HEAD request to the proxy and receives a response. It works perfect without threads. But with threads the main problem I'm having is that the threads are not starting on time. I can confirm this to some extent due to adding a sleep() call, and everything works fine. So whats the problem?

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <pthread.h>
    
    #define IP_PORT_SIZE 22
    
    struct arg_struct {
        char * addr;
    };
    
    void test_proxy (void * arguments)
    {
    
        struct arg_struct *args = arguments;
    
        printf("My Ip is:\n"); 
        char *ip;
        char *port;
        ip = strtok(args->addr, ":");
        port = strtok(NULL, ":");
    
        printf("%s:%s \n",ip,port);
    
        struct sockaddr_in server;
        int sockfd;
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
        server.sin_addr.s_addr = inet_addr(ip);
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(port));
                
        if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
            printf("Error connecting \n\n");
        }
        
        char request[] = "HEAD http://www.msn.com HTTP/1.0\r\n\r\n";
    
        if (send(sockfd, request, strlen(request), 0) < 0)
        {
            printf("Error writing \n\n");    
        }
    
        char server_reply[500];
        
        if (recv(sockfd, server_reply, 500, 0) < 0)
        {
            printf("Error receiving \n\n");
        }
    
        //printf("%s \n \n",server_reply);
        
        close(sockfd);
        
        if (strstr(server_reply,"HTTP/1.1 200") || 
            strstr(server_reply,"HTTP/1.1 302") ||
            strstr(server_reply,"HTTP/1.0 200") || 
            strstr(server_reply,"HTTP/1.0 302"))
        {
            //FILE * fp;
            //char address[IP_PORT_SIZE];
            //fp = fopen(output_file,"a");
            //sprintf(address, "%s:%s", ip, port);
            //fputs(address,fp);
            //fclose(fp);
        }    
    }
    
    int amount_ips (char file[]) {
        FILE * fp;
        int ch, number_of_lines = 0;
    
        fp = fopen(file,"r");
    
        do 
        {
            ch = fgetc(fp);
            if(ch == '\n')
                number_of_lines++;
        } while (ch != EOF);
    
        fclose(fp);
    
        return number_of_lines;
    }
    
    int main(int argc, char *argv[] ) {
            
        FILE * fp;
        int amount_of_ips;
        char line[IP_PORT_SIZE];    
        char file[100];
        strcpy(file,argv[1]);
        //char output_file[100];
        //strcpy(output_file,argv[2]);
    
        amount_of_ips = amount_ips(file);
        
        char ip_array[amount_of_ips][IP_PORT_SIZE];    
    
        fp = fopen(file,"r");
    
        int a;
        for (a = 0; a < amount_of_ips; a++)
        {
            fgets(line,IP_PORT_SIZE,fp);
            strcpy(ip_array[a], line);
        }
    
        fclose(fp);
    
        //test_proxies(ip_array, amount_of_ips, output_file);]
        pthread_t proxy_thread[amount_of_ips];
        struct arg_struct args[amount_of_ips];
    
        int b;
        for (b = 0; b < amount_of_ips; b++)
        {
            args[b].addr = (char *) &ip_array[b];
    
            // create the thread 
            if(pthread_create(&proxy_thread[b], NULL, test_proxy, &args[b])) {
                printf("Error creating");
            }
            //sleep(1);
        }
        
        int c;
        for (c = 0; c < amount_of_ips; c++)
        {
            if(pthread_join(proxy_thread[c], NULL)) {
    
                printf("Error joining thread\n");
            }
        }
    }
    To run just include a list a bunch of "http" proxies as the first argument in a text file.

    Any other suggestions are welcome.
    Last edited by watchintv; 05-12-2016 at 09:02 AM.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    strtok() is not thread safe. Use strtok_r() instead.

    gg

  3. #3
    Registered User
    Join Date
    May 2016
    Posts
    31
    Ok, thanks, I didn't know that. I added it.

    Still apparently not working.
    Last edited by watchintv; 05-12-2016 at 09:21 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Some points

    1. if (send(sockfd, request, strlen(request), 0) < 0)
    Any positive value (1,2,3,4 all the way up to whatever number you said) counts as success. You have to account for all the partial successes, then retry the send command with the part of the data that wasn't sent.

    2. if (recv(sockfd, server_reply, 500, 0) < 0)
    Ditto here - there is no guarantee that recv will fill the buffer with all the available data.
    Additionally, recv() does NOT append a handy \0 to make it safe to use all those str... functions.

    Code:
            if(pthread_create(&proxy_thread[b], NULL, test_proxy, &args[b])) {
                printf("Error creating");
            }
    Instead, try
    Code:
    test_proxy(&args[b]);
    You need to make sure your code actually works in a single thread before making it massively more complicated to debug by adding threads.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2016
    Posts
    31
    Ok, thanks for the advice. I'll look into handling the different return values. I wasn't really having too much of a problem with that but I agree. Great advice. And thanks for the tip about the null terminator, didn't know that. Besides that, thats the thing it does seem to work fine in one thread. So, I'm not sure why calling the sleep function even just for a second solves the problem.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > So, I'm not sure why calling the sleep function even just for a second solves the problem.
    Because as noted by Codeplug, strtok() is not thread safe, so a delay of 1 second gives plenty of time to get past the critical point in the code before the next thread runs.

    Sleep() doesn't solve the problem, it hides the problem.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    May 2016
    Posts
    31
    Ok, Im gonna have to play around with this for a little bit to see what the deal is... It seemed like I was still getting the same problems when I had fixed strtok, but I'll check again.

    Thanks
    Last edited by watchintv; 05-12-2016 at 11:55 AM.

  8. #8
    Registered User
    Join Date
    May 2016
    Posts
    31
    Yeah, It's still not working.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Post the latest code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    May 2016
    Posts
    31
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <pthread.h>
     
    #define IP_PORT_SIZE 22
     
    struct arg_struct {
        char * addr;
    };
     
    void test_proxy (void * arguments)
    {
     
        struct arg_struct *args = arguments;
     
        printf("My Ip is:\n"); 
        char *ip;
        char *port;
        char *ptr;
        ip = strtok_r(args->addr, ":", &ptr);
        port = strtok_r(NULL, ":", &ptr);
     
        printf("%s:%s \n",ip,port);
     
        struct sockaddr_in server;
        int sockfd;
     
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
     
        server.sin_addr.s_addr = inet_addr(ip);
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(port));
                 
        if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
            printf("Error connecting \n\n");
        }
         
        char request[] = "HEAD http://www.msn.com HTTP/1.0\r\n\r\n";
     
        if (send(sockfd, request, strlen(request), 0) < 0)
        {
            printf("Error writing \n\n");    
        }
     
        char server_reply[500];
         
        if (recv(sockfd, server_reply, 500, 0) < 0)
        {
            printf("Error receiving \n\n");
        }
     
        //printf("%s \n \n",server_reply);
         
        close(sockfd);
         
        if (strstr(server_reply,"HTTP/1.1 200") || 
            strstr(server_reply,"HTTP/1.1 302") ||
            strstr(server_reply,"HTTP/1.0 200") || 
            strstr(server_reply,"HTTP/1.0 302"))
        {
            //FILE * fp;
            //char address[IP_PORT_SIZE];
            //fp = fopen(output_file,"a");
            //sprintf(address, "%s:%s", ip, port);
            //fputs(address,fp);
            //fclose(fp);
        }    
    }
     
    int amount_ips (char file[]) {
        FILE * fp;
        int ch, number_of_lines = 0;
     
        fp = fopen(file,"r");
     
        do
        {
            ch = fgetc(fp);
            if(ch == '\n')
                number_of_lines++;
        } while (ch != EOF);
     
        fclose(fp);
     
        return number_of_lines;
    }
     
    int main(int argc, char *argv[] ) {
             
        FILE * fp;
        int amount_of_ips;
        char line[IP_PORT_SIZE];    
        char file[100];
        strcpy(file,argv[1]);
        //char output_file[100];
        //strcpy(output_file,argv[2]);
     
        amount_of_ips = amount_ips(file);
         
        char ip_array[amount_of_ips][IP_PORT_SIZE];    
     
        fp = fopen(file,"r");
     
        int a;
        for (a = 0; a < amount_of_ips; a++)
        {
            fgets(line,IP_PORT_SIZE,fp);
            strcpy(ip_array[a], line);
        }
     
        fclose(fp);
     
        //test_proxies(ip_array, amount_of_ips, output_file);]
        pthread_t proxy_thread[amount_of_ips];
        struct arg_struct args[amount_of_ips];
     
        int b;
        for (b = 0; b < amount_of_ips; b++)
        {
            args[b].addr = (char *) &ip_array[b];
     
            // create the thread 
            if(pthread_create(&proxy_thread[b], NULL, test_proxy, &args[b])) {
                printf("Error creating");
            }
            //sleep(1);
        }
         
        int c;
        for (c = 0; c < amount_of_ips; c++)
        {
            if(pthread_join(proxy_thread[c], NULL)) {
     
                printf("Error joining thread\n");
            }
        }
    }

    I still have not accounted for send and recv yet, so bare with me...

  11. #11
    Registered User
    Join Date
    May 2016
    Posts
    31
    I was using tinyproxy to test locally

  12. #12
    Registered User
    Join Date
    May 2016
    Posts
    31
    Perhaps I'm not using strtok_r properly?

  13. #13
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by watchintv View Post
    Perhaps I'm not using strtok_r properly?
    You're using it correctly, except (for me on linux, at least) you should put this before including string.h:
    Code:
    #define _POSIX_SOURCE
    Your thread function should return a void*, which can be NULL. You should compile with a high warning level: gcc -W -Wall -pedantic (-W is the same as -Wextra; pedantic can be a little pedantic).

    Instead of printing a generic error message (and continuing on anyway!) you should use perror to get some helpful information and perhaps return from the thread. E.g.,
    Code:
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return NULL;
    }
    You don't need the struct around your argument string.

    You don't need a different index variable for each loop (unless they're nested).

    Your amount_ips function is better named count_lines since that's what it's doing. Actually it's counting newlines, which is not quite the same thing as it's possible for the last line to be missing a newline. It could be rewritten to handle that:
    Code:
      
    int count_lines(const char *filename) {
        int ch, lastch = '\0', count = 0;
        FILE *fp = fopen(filename, "r");
      
        while ((ch = fgetc(fp)) != EOF) {
            if (ch == '\n')
                count++;
            lastch = ch;
        }
    
        if (lastch != '\0' && lastch != '\n')  // count last line with missing newline
            count++;
    
        fclose(fp);
      
        return count;
    }
    Last edited by algorism; 05-12-2016 at 12:50 PM.

  14. #14
    Registered User
    Join Date
    May 2016
    Posts
    31
    Ok, thanks for the suggestions everyone. So far, I added the definition for POSIX_SOURCE. And its still not working. I removed the strtok_r and used the normal function outside the thread and I was still having problems. But no problem with sleep. And I had all the test_proxy function commented out except for a couple printf statements. Strange.

    Still not working.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Are you saying it doesn't work if you just call test_proxy() directly, rather than via a thread?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multiple processes running concurrently in c
    By bungkai in forum C Programming
    Replies: 3
    Last Post: 02-07-2012, 04:15 PM
  2. Replies: 13
    Last Post: 12-09-2008, 11:09 AM
  3. Multiple theads to process video files
    By matth in forum C++ Programming
    Replies: 0
    Last Post: 07-15-2005, 02:55 PM
  4. Replies: 1
    Last Post: 05-01-2003, 02:52 PM
  5. Running multiple programs
    By Kespoosh in forum C++ Programming
    Replies: 2
    Last Post: 03-17-2003, 04:53 PM

Tags for this Thread