Segmentation fault on TCP server.

I have developed a server in C ++ and a client that connects to it.

Both are run on a PC with linux.

When we run the server and a client is connected to it, a
Segmentation fault on the server, specifically, on the line:
sClient = ((struct ThreadArgs *) threadArgs) -> sClient;

Attached is the source code of the server:




ServerTCP.h :
---------------

#ifndef _SERVER_TCP_
#define _SERVER_TCP_


#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>


struct ThreadArgs
{
int sClient;
};

typedef void* (*THREAD_FUNC_PTR)(void *);


class ServerTCP
{
private:
int sPort;

public:
ServerTCP(unsigned int port);
void *ThreadMain(void *threadArgs);
void waitConnections();
};

#endif





ServerTCP.cpp :
------------------

#include "ServerTCP.h"

#define MAX_DATA_LENGTH 65000


ServerTCP::ServerTCP (unsigned int port)
{
sPort = port;
}



void* ServerTCP::ThreadMain(void *threadArgs)
{
int sClient;

int ret;
char data_in[MAX_DATA_LENGTH];

pthread_detach(pthread_self() ) ;

//>>> SIGSEGV, Segmentation fault
sClient = ((struct ThreadArgs *) threadArgs) -> sClient;

free(threadArgs);
ret = 1;
while (ret != 0)
{
ret = recv(sClient, data_in, MAX_DATA_LENGTH, 0);
if (ret < 0)
{
printf("Error: Call to recv(sClient, frame_in, sizeof(frame_in), 0); has failed.\n");
exit(1);
}
}

close(sClient);
return NULL;
}



void ServerTCP::waitConnections()
{
int ret;
unsigned int iPort, iAddrLen;
int sListen, sClient;
struct sockaddr_in addr, remote_addr;
pthread_t threadID;
struct ThreadArgs *threadArgs;


sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen < 0)
{
printf("Error: Call to socket(AF_INET, SOCK_STREAM, IPPROTO_IP); has failed.\n");
exit(1);
}

iPort = sPort;

addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);


sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen < 0)
{
printf("Error: Call to socket(AF_INET, SOCK_STREAM, IPPROTO_IP); has failed.\n");
exit(1);
}

addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(sListen, (struct sockaddr *) &addr, sizeof(addr));

if(ret < 0)
{
printf("Error: Call to bind(sListen, (struct sockaddr *) &addr, sizeof(addr)); has failed.\n");
exit(1);
}

ret = listen(sListen, 10);
if(ret < 0)
{
printf("Error: Call to listen(sListen, 10); has failed.\n");
exit(1);
}

for(;;)
{
printf("Waiting for connection from a client...\n");

iAddrLen = sizeof(remote_addr);

sClient = accept(sListen, (struct sockaddr *) &remote_addr, &iAddrLen);
if(sClient < 0)
{
printf("Error: Call to accept(sListen, (struct sockaddr *) remote_addr, sizeof(remote_addr)); has failed.\n");
exit(1);
}

printf("%s has connected.\n\n", inet_ntoa(remote_addr.sin_addr));

if ((threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs))) == NULL)
{
printf("Error: malloc() for threadArgs has failed.\n");
exit(1);
}

threadArgs -> sClient = sClient;
printf ("sClient = %d, threadArgs -> sClient = %d\n", sClient, threadArgs -> sClient);

if (pthread_create(&threadID, NULL, (THREAD_FUNC_PTR)&ServerTCP::ThreadMain, (void *)threadArgs) != 0)
{
printf("Error: pthread_create() has failed.\n");
exit(1);
}
}
}



int main(int argc, const char* argv[])
{
ServerTCP serverTCP(5772);

serverTCP.waitConnections();

return 0;
}




Last edited on
As someone on the other site said, you need to make ServerTCP::ThreadMain() static. Remember, non static member functions have an extra hidden parameter (the "this" pointer), so there are really two parameters to ThreadMain(): "this" and "threadArgs". By passing it to pthread_create, you're causing it to be called with just one parameter.

If you don't believe me, try adding this to the beginning of ThreadMain():
printf("this=%p. ThreadArgs=%p\n", this, threadArgs);
I'm nearly certain that you'll find that the pointers are the same.

If threadMain really must be a normal member then you'll need a glue function to call it. The code below is untested:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  // Parameter block for the threadMain() function
struct ThreadParams {
   ThreadParams(int f, ServerTCP *s) :
      sClient(f), server(s) {}
    int sClient;
    ServerTCP *server;
};

void *ServerTCP::threadMain(int sClient)  // Change this to take sClient directly
{
...
}

// static function, not a member of any class. This unpacks the params, calls
// ServerTCP::ThreadMain() and deletes the parameter block.
static void *threadMain(void *arg)
{
    ThreadParams *params = (ThreadParams*)arg;
    return params->ThreadMain(params->sClient);
    delete(params);
}

...
void ServerTCP::waitConnections()
{
...
    ThreadParams *params = new ThreadParams(sClient, this);
    // threadMain takes ownership of params.
    if (pthread_create(&threadID, NULL,  threadMain, params) != 0) ...
}
Topic archived. No new replies allowed.