I'm creating a TCP socket-based server-client application for a roulette game. Before compiling the server, the admin needs to input two arguments for how the server should work: one for the port, and the other for the roulette's required time to spin. However, when I try to compile the code it gives me a segmentation fault error. The code works fine if all references to roulette_time are taken out, though.
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#define BACKLOG 15
long bank = 0;
typedef struct pthread_arg_t{
int new_socket_fd;
struct sockaddr_in client_address;
int port;
int *roulette_time;
/*Inserire le variabili passate dal client qui*/
int picked_num;
long stake;
int won;
}pthread_arg_t;
void *pthread_routine(void *arg);
void signal_handler(int signal_number);
int main(int argc, char *argv[]){
int port, socket_fd, new_socket_fd, chosen_number, won, roulette_time;
long stake;
struct sockaddr_in address;
pthread_attr_t pthread_attr;
pthread_arg_t *pthread_arg;
pthread_t pthread;
socklen_t client_address_len;
port = atoi(argv[1]);
roulette_time = atoi(argv[2]);
if(port == NULL){
printf("Inserisci il port qui\n");
scanf("%d",&port);
}
if(roulette_time == NULL){
printf("Inserisci il tempo minimo da far trascorrere prima dell'azionamento della roulette\n");
scanf("%d",&roulette_time);
}
pthread_arg->roulette_time = &roulette_time;
memset(&address,0,sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("creazione socket");
exit(1);
}
if(bind(socket_fd,(struct sockaddr*)&address, sizeof(address)) == -1){
perror("binding");
exit(1);
}
if(listen(socket_fd, BACKLOG) == -1){
perror("listen");
exit(1);
}
if((signal(SIGPIPE, SIG_IGN) == SIG_ERR) || (signal(SIGTERM, signal_handler) == SIG_ERR) || (signal(SIGINT, signal_handler) == SIG_ERR)){
perror("signal");
exit(1);
}
if(pthread_attr_init(&pthread_attr) != 0){
perror("pthread_attr_init");
exit(1);
}
if(pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED) != 0){
perror("pthread_attr_setdetachstate");
exit(1);
}
while(1){
pthread_arg = (pthread_arg_t *)malloc(sizeof *pthread_arg);
if(!pthread_arg){
perror("malloc");
continue;
}
client_address_len = sizeof(pthread_arg->client_address);
new_socket_fd = accept(socket_fd, (struct sockaddr *)&pthread_arg->client_address,&client_address_len);
if(new_socket_fd == -1){
perror("accept");
free(pthread_arg);
continue;
}
pthread_arg->new_socket_fd = new_socket_fd;
/*Inizializza tutte le variabili qui*/
chosen_number = pthread_arg->picked_num;
stake = pthread_arg->stake;
won = pthread_arg->won;
if(pthread_create(&pthread, &pthread_attr, pthread_routine, (void*)pthread_arg) != 0){
perror("pthread_create");
free(pthread_arg);
continue;
}
}
return 0;
}
void *pthread_routine(void *arg){
pthread_arg_t *pthread_arg = (pthread_arg_t *)arg;
int new_socket_fd = pthread_arg->new_socket_fd;
struct sockaddr_in client_address = pthread_arg->client_address;
int roulette_num, picked_num, won, accept_time = pthread_arg->roulette_time;
long stake;
time_t start, end;
sem_t mutex;
free(arg);
/*Inserisci codice roulette qui*/
while(1){
if(start == NULL){
start = time(NULL);
end = start + accept_time;
}
read(new_socket_fd, &picked_num, sizeof(picked_num));
read(new_socket_fd, &stake, sizeof(stake));
printf("Puntata ricevuta: numero %d, %d crediti\n",ntohl(picked_num), ntohl(stake));
bank = bank + stake;
printf("Soldi del banco: %d crediti\n",ntohl(bank));
start = time(NULL);
if(start >= end){
roulette_num = (rand() % (36 - 0 + 1)) + 0;
printf("Numero estrtatto dalla roulette: %d\n",roulette_num);
int converted_roulette_num = htonl(roulette_num);
write(new_socket_fd,&converted_roulette_num,sizeof(int));
if(read(new_socket_fd,&won,sizeof(int)) == 1){
int converted_bank = htonl(bank);
write(new_socket_fd,&converted_bank,sizeof(converted_bank));
bank = 0;
}
start = NULL;
}
}
close(new_socket_fd);
return NULL;
}
void signal_handler(int signal_number){
}
Edit: The input that this application accepts is ./server [socket port number] [seconds to activate roulette]
, for example: ./server 24106 30
(in this case 24106 is the socket port number, and we're asking the roulette to spin after 30 seconds have passed).
The output should appear in the following way: after the server receives an input from a connected client, the server prints the received number and the stake. After the amount of time passed as argument passed, the roulette spins and the server prints out the extracted number. However, as mentioned earlier, this only happens if I remove every instance of roulette_time from the code - otherwise I get Segmentation fault (core dumped)
every time I try to run it.