2

I have the following code serving as main loop for a server that accepts incoming socket connections.

At the moment the macro OperationMode is defined as 1 so it will execute the pthread logic.

for (hit = 1 ;; hit++) {
        printf("Got here\n\n");

        length = sizeof(cli_addr);

        /* block waiting for clients */
        socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);

        if (socketfd < 0)
                printf("ERROR system call - accept error\n");
        else
        {
                printf("Testing\n\n\n");
                #ifdef OperationMode
                        pthread_t thread_id;
                        if(pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL))
                        {
                                perror("could not create thread");
                                return 1;
                        }
                #else
                        pid = fork();
                        if(pid==0)
                        {
                                ftp(socketfd, hit);
                        }
                        else
                        {
                                close(socketfd);
                                kill(pid, SIGCHLD);
                        }
                #endif
        }
}

I'm able to create a thread for the first incoming socket connection but once I iterate over the loop I get segmentation fault error in the line

socketfd = accept(listened, (struct sockaddr *) &cli_addr, &length);

My attendFTP function has the following code

void *attendFTP(int fd, int hit)
{
    ftp(fd, hit);
    return NULL;
}

This works perfect for the fork implementation. How can I fix the segmentation fault error?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
rafaelcpalmeida
  • 874
  • 1
  • 9
  • 28
  • Unless `attendFTP()` is a function returning a pointer to a function, you are using `pthread_create()` incorrectly. – EOF Mar 31 '16 at 20:17
  • @EOF I've added my `attendFTP()` function. But I believe I'm using it correctly – rafaelcpalmeida Mar 31 '16 at 20:21
  • You are not using it correctly. The prototype is `int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);`. You'll probably need to pass a pointer to a `struct` if you need multiple arguments for the function you want the thread to execute. – EOF Mar 31 '16 at 20:23

1 Answers1

2
pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL);

This code passess result of a call to attendFTP() with given paramters - and this result is always NULL.

So pthread_create is trying to launch a function at NULL address and, correspondingly, fails.

If you run your compiler with -pedantic argument, compiler will tell you that what you are doing is wrong. Without -pedantic, gcc allows for some 'extensions', which might hide errors. Btw, this is why -pedantic is, in my view, a must.

What you actually want is to pass some arguments to your threading function. Unfortunately, it is really convoluted in C pthreads, and requires you to allocate and deallocate the said struct. Something like this:

struct args {
    int fd;
    int hit;
};
...
pthread_t thread_id;
struct args* args = malloc(sizeof(struct args));
args->fd = socketfd;
args->hit = hit;
if(pthread_create(&thread_id, NULL, attendFTP, args))
....

void* attendFTP(void* vargs)
{
    struct args* args = vargs;
    ftp(args->fd, args->hit);
    free(args);
    return NULL;
}
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • But the first iteration of the loop executes successfully, shouldn't it fail? – rafaelcpalmeida Mar 31 '16 at 20:38
  • @rafaelcpalmeida, nope, it doesn't. But since you are calling attendFTP, you are basically executing it in the same thread first (without any multithreading) and see some results. Than pthread is created and crashes the app. – SergeyA Mar 31 '16 at 20:40
  • So the first calling is not truly multithreading? How can I pass arguments inside attendFTP function? Can you share some example? Edit: I managed to get it working using a struct with the arguments, as EOF told. – rafaelcpalmeida Mar 31 '16 at 20:42
  • @rafaelcpalmeida, provided some code. I am not sure if what you did is correct - if you didn't dynamically allocate your arguments struct, you did it wrong. – SergeyA Mar 31 '16 at 20:48
  • Everything is working perfectly Sergey. I've also learnt about -pedantic, I had no idea! – rafaelcpalmeida Mar 31 '16 at 20:50
  • Are you seriously suggesting to dereference a pointer after it has been `free()`d? – EOF Mar 31 '16 at 20:51