Weird Segmantation fault on writing a to a file c - c

In this case of the project that am working on , am receiving a message and i want to send a response by writing a message to the file descriptor.But the problem is that the write function returns Segmentation Fault and i dont know why. For example i receive a message going to the right case and send response by writing to a file when i use write it shows that the message went to the destination but after that returns segmentation fault.If instead of write use a printf it works and doesnt show segmentation fault .Can any one help me with that ?
typedef enum operation{
insert,
read_reg,
info,
error
}Operation;
typedef struct request{
Operation operation;
int ID;
int counter;
}Request;
int **regs;
fd=open(port,O_RDWR|O_NOCTTY);
if(fd==-1){
perror(port);
exit(1);
}
regs=(int **)malloc(2*sizeof(int*));
if(regs==NULL){
printf("Cant create data base for registers\n");
exit(1);
}
for(int i=1;i<=2;i++){
regs[i]=(int*)malloc(SIZE*sizeof(int));
if(regs[i]==NULL){
exit(1);
}
}
regs[1][0]=1;
regs[2][0]=3;
char str[12];
char buffer[255];
while(1){
//Clean buffer
memset(buffer,0,SIZE);
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
timeout.tv_sec=100;
timeout.tv_usec=0;
status=select(40,&readfd,NULL,NULL,&timeout);
if(status==0){
printf("Cannot receive data from client\n");
printf("\tTime Out\n");
exit(1);
}
read_num=read(fd,buffer,sizeof(buffer));
if(read_num<0) perror("Error in reading file descriptor\n");
if(read_num>0){
//while(1){
fl.l_type = F_RDLCK; /* read lock */
fl.l_whence = SEEK_SET; /* beginning of file */
fl.l_start = 0; /* offset from l_whence */
fl.l_len = 0; /* length, 0 = to EOF */
fl.l_pid = getpid(); /* PID */
fcntl(fd, F_SETLKW, &fl);
request=parse_request(buffer);
if(request){
switch(request->operation){
case info:
write(fd,"OK\n",1);
break;
case read_reg:
write(fd,"OK\n",1);
printf("prepei na diabaso reg\n");
break;
case insert:
printf("edo vazo timi\n");
write(fd,"OK\n",1);
break;
case error:
printf("prepei na petakso error\n");
write(fd,"OK\n",1);
break;
}
printf("prepei na me deis meta apo kathe break\n");
}
printf("kai edw prepei na me deis \n");
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl); // unset lock
//}
}
printf("edw ?\n");
}
parse_request is a function that splits the message and determines information about it.
Request *parse_request(char *buffer){
char *token=NULL,*value=NULL;
Request *rep=NULL;
char string_split[4];
int i=0;
rep=(Request*)malloc(sizeof(Request));
rep->counter=0;
token=strtok(buffer,"=");
//extract value
value=strtok(NULL,"=");
token=strtok(token,"+");
//extract register
token=strtok(NULL,"+");
//Set up registers ID
rep->ID=atoi(&token[strlen(token)-1]);
//Set up operation type
if(!value){
rep->operation=read_reg;
//printf("Operation :read\n");
}else{
if(strcmp(value,"?")==0){
rep->operation=info;
//printf("Operation :info\n");
}else{
//check if number is valid
if(isValid(value,rep)==1){
rep->operation=insert;
//printf("Operation :insert\n");
//printf("am gonna insert value:%d\n",atoi(value));
regs[rep->ID][rep->counter++]=atoi(value);
printf("%d\n",regs[rep->ID][rep->counter++]=atoi(value));
}else{
rep->operation=error;
//printf("Operation :error\n");
}
}
}
return rep;
}

regarding a buffer that contains:
AT+<REG>=<VALUE>
the first call to strtok() replaces the + with a NUL byte.
A second call to strtok() does not find a + in the buffer, so continues to search through memory until some 'random' + is encountered.
Now you have a pointer token pointing to memory that your program should not access.
Then the program tries to output the memory at that 'invalid' 'token' pointer. The result is a seq fault event.

Related

File handle segfault

Implementing a data link protocol. I managed to send the whole file through the virtual serial port - which should be the hard part. The weird thing is I'm getting a segfault on fclose() when trying to save it. The file is being created, which means the open is successful, but nothing it being stored in it. Even changed the implementation to buffer all the file into memory before saving it.
int app_rx(const char* outputFile){
file_data_t fileData;
if(!receive_ctrl_pckt(&fileData)){
printf("Could not receive control packet\n");
return FAILURE;
}
printf("Receiving file [%s]\nFile size: %d\n", fileData.fileName, fileData.fileSize);
unsigned char fileBuffer[fileData.fileSize];
int fileIndex = 0;
int totalBytes = 0;
int stop = 0;
size_t sqNo = 0;
int bytes;
FILE* out = fopen(outputFile, "w");
do{
activeBuffer = (activeBuffer + 1) % 2;
printf("Receiving packet %lu\n", sqNo);
bytes = llread(BUFFERS[TMP_BUFFER]);
if(bytes == DUP_ERR){
printf("Duplicate data. Discarding packet\n");
}
else if (bytes == WH_ERR){
printf("Invalid header. Discarding packet\n");
}
else if (bytes == WD_ERR){
printf("Corrupted data. Awaiting retransmission\n");
}
else{
printf("Packet %lu successfully received\n", sqNo);
int retrieveRes = retrieve_payload(sqNo);
switch(retrieveRes){
case CTRL_END: {
stop = 1;
break;
}
case FAILURE: {
printf("Unknown error\nExiting...");
exit(1);
}
case SQ_ERR:{
printf("Unsynchronized packets\nExiting");
exit(1);
}
default:{
for(int i = 0; i < retrieveRes; i++){
fileBuffer[fileIndex] = BUFFERS[activeBuffer][i];
fileIndex++;
}
sqNo = (sqNo + 1) % 255;
totalBytes += bytes;
break;
}
}
}
}while(!stop);
printf("file index: %d\n", fileIndex);
fwrite(fileBuffer, sizeof(unsigned char), fileIndex, out);
printf("here\n");
fclose(out);
if(totalBytes == fileData.fileSize){
return SUCCESS;
}
else{
return FAILURE;
}
}
Stdout:
Packet 9 successfully received
Receiving packet 10
Asserting data integrity
Packet 10 successfully received
Receiving packet 11
Asserting data integrity
Packet 11 successfully received
file index: 10968
here
make: *** [Makefile:35: run_rx] Segmentation fault (core dumped)
Giant method, I know. Just trying to get it under before refactoring properly. Can't for the sake of nothing figure out what's going on. I know this works because I've copied the exact same file using this method with a simple copyfile.c test driver which mimics the cp command.
Any ideas? I find it particularly odd that it creates the output file, but doesn't write anything on it.
EDIT: managed to get it going by opening the file right before writting to it. Still don't quite understand what happened
There is a potential buffer overflow risk for array fileBuffer, except that retrieveRes is guaranteed smaller or equal than fileData.fileSize, if there is a buffer overflow, pointer out may be overwritten and caused a segment fault when call fclose. The buffer overflow can be verified by print the value of out before do/while loop and call to fclose.

Fail to read/write struct to fifo recursively in C

In an exercise problem, I am required to build a client program (write first) that opens a .txt file, put each line and the total bytes of each line into a struct variable and then send it out to the server program (read first). Right after this is done, the client program will also receive a struct file (similarly only has char * and int attributes) from the server program.
// Below are global variables in both programs
#define BUFSIZE 1024
struct info_pack
{
char line[BUFSIZE]; // the line to receive messages
int bytes; // the bytes of data transferred
};
char fifo_path[] = "./my_fifo";
struct info_pack info_w; // the info_pack for writing each line in text.txt
struct info_pack info_r; // the info_pack for reading feedback info_pack sent from the server program
First is the client program:
// the main() in the client program
int main()
{
int fd;
int i = 0, index = 1, bytes = 0, line_length, fifo_read;
char *file_path = "/home/text.txt";
FILE *fd2;
mkfifo(fifo_path, 0666);
if ((fd2 = fopen(file_path, "r")) < 0)
{
perror("Opening file");
return -1;
}
else
{
printf("Successfully open the target file\n");
while (fgets(info.line, BUFSIZE, fd2) != NULL)
// the "segmentation fault" error appears right after this line
{
info_w.bytes = strlen(line);
fd = open(fifo_path, O_WRONLY);
printf("The %d th line sent out is: %s\n%d bytes are sent\n\n",
index, info_w.line, info_w.bytes);
write(fd, &info_w, sizeof(info_w) + 1);
close(fd);
fd = open(fifo_path, O_RDONLY);
fifo_read = read(fd, &info_r, sizeof(info_r));
close(fd);
if (fifo_read > 0)
{
printf("Feedback: %s\nand %d bytes are returned\n", info_r.line, info_r.bytes);
}
}
printf("All data is successfully transfered\n");
}
return 0;
}
Then is the server program
// the main() in the server program
int main()
{
int fd, fifo_read;
int line_length;
char *feedback = "SUCCESS";
strcpy(info_w.line, feedback);
info_w.bytes = strlen(feedback);
// define a constant info_pack variable to send to the client program
if (mkfifo(fifo_path, 0666) < 0)
{
perror("client end: ");
exit(-1);
}
while (1)
// This server program will wait for any one single client's message
// This server program can only be terminated by manually input signals (like ^\)
{
fd = open(fifo_path, O_RDONLY);
printf("waiting for client's message\n");
fifo_read = read(fd, &info_r, sizeof(info_r));
close(fd);
if (fifo_read > 0)
// if receive the struct variable, print all of its attributes
{
if (info_r == NULL)
printf("Found no lines sent from the client\n");
else
printf("Read from fifo:\n %s\n(in info)%d bytes read (actually)%d bytes read\n", info_r.line, info_r.bytes, fifo_read);
}
else
{
sleep(1);
printf("Fail to read data from the client\n");
}
// Because of the error in client program this server program
// always pause here
fd = open(fifo_path, O_WRONLY);
printf("Now writing feedback to the client\n");
write(fd, info_w, sizeof(info_w));
close(fd);
}
}
Could anyone explain why the segmentation fault error appears in the client program? Then I can test if the both the client and the server can co-op properly.By the way, I read this post already but, in this post, it is a one-time data stream and I cannot find any hints in it.

How to use poll function correctly with socket

Hi I want to use the poll function to wait the permission to read the stdin and send the result in a socket and after that i want to wait the permission to write this result in the stdout. I tried to use poll as you can see in the code below but it doesn't work correctly when i run the main program with two terminal one as server and the other as client.Nothing appear on my stdout even with a flush and after the timout i get this message
Did not receive sent data in the last 5 sec.Received only 0 bytes out of 1024
Could you tell me if I use the function correctly or how should I use it
Thanks
void read_write_loop(int sfd){
int n;
char buffer_in[1024];
struct pollfd poll_files_descriptors[2];
int stdin_to_stdout;
poll_files_descriptors[0].fd = STDIN_FILENO;
poll_files_descriptors[0].events = POLLIN;
//see if you can wirte to stdout
poll_files_descriptors[1].fd = STDOUT_FILENO;
poll_files_descriptors[1].events = POLLOUT;
stdin_to_stdout = poll(poll_files_descriptors, 2 , 2000 );
if(stdin_to_stdout == -1){
perror("poll not working ");
return;
}
while( !feof(stdin)){
if(poll_files_descriptors[0].revents & POLLIN){
//readable et il y qqch
n = fread(&buffer_in,sizeof(buffer_in),1, stdin);
if(n==0) break;
int sent_status = send(sfd, buffer_in, n, 0);
if(sent_status == -1){
printf("nothing sent");
}
}
if(poll_files_descriptors[1].revents & POLLOUT){
int receive_status = recv(sfd, buffer_in, n , 0);
if(receive_status == -1){ // number of bytes
printf("nothing received");
}
fwrite(&buffer_in, sizeof (char), receive_status,stdout );
}
}
}

Message queque mq send error. Bad file descriptor

I am trying to write to my message queue (mq_send).
Here is my code for opening the queue first and then for writing to it.
Opening:
int MQconnect (mqd_t * mq, char * name)
{
//printf("hello from MQconnect\n");
do{
mq=mq_open(name, O_WRONLY); //O_RDONLY
}while(mq==-1);
if(mq== -1){
return 0;
}
else
return 1;
// Connects to an existing mailslot for writing Uses mq as reference pointer, so that you can reach the handle from anywhere/
// Should return 1 on success and 0 on fail*/
}
Writing:
int MQwrite (mqd_t mq, void * sendBuffer) // (const char) sendBuffer
{
int nrOfBytes = mq_send(mq, (const char)sendBuffer, 1024, 10);
printf("\n%d", nrOfBytes);
return nrOfBytes; //nrOfBytes;
// Write a msg to a mailslot, return nr Uses mq as reference pointer, so that you can reach the handle from anywhere
// should return number of bytes read */
}
The opening works fine but I cant write to the message queue.
mq_send return -1 as return value and the error message is:
Value of errno: 9
Error printed by perror: Bad file descriptor
Error: Bad file descriptor
The call to the above functions happens from this function:
void * mqClient(void * arg){
pthread_mutex_lock(&mutex);
char answer[20];
mqd_t mq_on_server;
usleep(1000);
int response = MQconnect(&mq_on_server, "/servermq");
if(response==0){
printf("something went wrong with MQconnect\n");
}
else{
//This loop continously scans planets given by the user
//while(!(0)){
printf("\nWrite to mailbox: ");
scanf("%s", answer);
MQwrite (mq_on_server, &answer);
int c;
while ( (c = getchar()) != '\n' && c != EOF);
//fflush(stdout);
//}
}
pthread_mutex_unlock(&mutex);
}
Anyone have an idea why I am getting this kind of error? My friend has the exact same code and for him it is working.
You forgot to dereference the given pointer in MQconnect.
int MQconnect (mqd_t * mq, char * name)
{
//printf("hello from MQconnect\n");
#if 0
/* wrong part */
do{
mq=mq_open(name, O_WRONLY); //O_RDONLY
}while(mq==-1);
if(mq== -1){
#else
/* fixed code */
do{
*mq=mq_open(name, O_WRONLY); //O_RDONLY
}while(*mq==-1);
if(*mq== -1){
#endif
return 0;
}
else
return 1;
// Connects to an existing mailslot for writing Uses mq as reference pointer, so that you can reach the handle from anywhere/
// Should return 1 on success and 0 on fail*/
}

Segfault on Server after Multithreading in C

So I'm trying to code a multi-threading server. I've spent an enormous time on the internet figuring out the correct way to do this and the answer as always seems to be it depends. Whenever I execute my code, the client successfully connects, and executes but when the thread terminates and returns to the while loop the whole program segfaults.
I probably could use a good spanking on a few other things as well such as my usage of global variables. The entirety of code is below, sorry for the inconsistent space/tabbing.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <signal.h>
#include <math.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
/* ---------------------------------------------------------------------
This is a basic whiteboard server. You can query it, append to it and
clear in it. It understands both encrypted and unencrypted data.
--------------------------------------------------------------------- */
struct whiteboard {
int line;
char type;
int bytes;
char string[1024];
} *Server;
int serverSize, threadcount, id[5];
bool debug = true;
struct whiteboard *Server;
pthread_mutex_t mutex;
pthread_t thread[5];
/* -------------------------------------------
function: sigint_handler
Opens a file "whiteboard.all" in writemode
and writes all white board information in
command mode.
------------------------------------------- */
void sigint_handler(int sig)
{
if (debug) printf("\nInduced SIGINT.\n");
FILE *fp;
fp=fopen("whiteboard.all","w");
int x=0;
for (x;x<serverSize;x++) // Loop Responsible for iterating all the whiteboard entries.
{
if (debug) printf("#%d%c%d\n%s\n",Server[x].line,Server[x].type,Server[x].bytes,Server[x].string);
fprintf(fp,"#%d%c%d\n%s\n",Server[x].line,Server[x].type,Server[x].bytes,Server[x].string);
}
if (debug) printf("All values stored.\n");
free(Server); // Free dynamically allocated memory
exit(1);
}
/* -------------------------------------------
function: processMessage
Parses '!' messages into their parts -
returns struct in response.
------------------------------------------- */
struct whiteboard processMessage(char * message)
{
int lineNumber, numBytes;
char stringType, entry[1028];
if (debug) printf("Update Statement!\n");
// Read line sent by Socket
sscanf(message,"%*c%d%c%d\n%[^\n]s",&lineNumber,&stringType,&numBytes,entry);
if (debug) printf("Processed: Line: %d, Text: %s\n",lineNumber,entry);
// Parse information into local Struct
struct whiteboard Server;
Server.line = lineNumber;
Server.type = stringType;
Server.bytes = numBytes;
strcpy(Server.string,entry);
// If there is no bytes, give nothing
if (numBytes == 0)
{
strcpy(Server.string,"");
}
return Server;
}
/* -------------------------------------------
function: handleEverything
Determines type of message recieved and
process and parses accordingly.
------------------------------------------- */
char * handleEverything(char* message, struct whiteboard *Server, char* newMessage)
{
bool updateFlag = false, queryFlag = false;
// If message is an Entry
if (message[0] == '#')
{
if (debug) printf("Triggered Entry!\n");
// Create Temporary Struct
struct whiteboard messageReturn;
messageReturn = processMessage(message);
// Store Temporary Struct in Correct Heap Struct
Server[messageReturn.line] = messageReturn;
sprintf(newMessage,"!%d%c%d\n%s\n",messageReturn.line, messageReturn.type, messageReturn.bytes, messageReturn.string);
return newMessage;
}
// If message is a query
if (message[0] == '?')
{
if (debug) printf("Triggered Query!\n");
int x;
queryFlag = true;
sscanf(message,"%*c%d",&x); // Parse Query
if (x > serverSize) // Check if Query out of Range
{
strcpy(newMessage,"ERROR: Query out of Range.\n");
return newMessage;
}
sprintf(newMessage,"!%d%c%d\n%s\n",Server[x].line,Server[x].type,Server[x].bytes,Server[x].string);
if (debug) printf("newMessage as of handleEverything:%s\n",newMessage);
return newMessage;
}
}
/* -------------------------------------------
function: readFile
If argument -f given, read file
process and parse into heap memory.
------------------------------------------- */
void readFile(char * filename)
{
FILE *fp;
fp=fopen(filename,"r");
int line, bytes, count = 0, totalSize = 0;
char type, check, string[1028], individualLine[1028];
// Loop to determine size of file. **I know this is sloppy.
while (fgets(individualLine, sizeof(individualLine), fp))
{
totalSize++;
}
// Each line shoud have totalSize - 2 (to account for 0)
// (answer) / 2 to account for string line and instruction.
totalSize = (totalSize - 2) / 2;
serverSize = totalSize+1;
if (debug) printf("Total Size is: %d\n",serverSize);
// Open and Allocate Memory
fp=fopen(filename,"r");
if (debug) printf("File Mode Calloc Initialize\n");
Server = calloc(serverSize+2, sizeof(*Server));
// Write to Heap Loop
while (fgets(individualLine, sizeof(individualLine), fp)) {
if (individualLine[0] == '#') // Case of Header Line
{
sscanf(individualLine,"%c%d%c%d",&check,&line,&type,&bytes);
if (debug) printf("Count: %d, Check:%c, Line:%d, Type: %c, Bytes:%d \n",count,check,line,type,bytes);
Server[count].line = line;
Server[count].type = type;
Server[count].bytes = bytes;
count++;
}
else
{
// For case of no data
if (individualLine[0] == '\n')
{
strcpy(string,"");
}
// Then scan data line
sscanf(individualLine,"%[^\n]s",string);
if (debug) printf("String: %s\n",string);
strcpy(Server[count-1].string,string);
}
}
return;
}
void *threadFunction(int snew)
{
char tempmessage[1024], message[2048];
// Compile and Send Server Message
strcpy(tempmessage, "CMPUT379 Whiteboard Server v0\n");
send(snew, tempmessage, sizeof(tempmessage), 0);
// Recieve Message
char n = recv(snew, message, sizeof(message), 0);
pthread_mutex_lock(&mutex);
if (debug) printf("Attempt to Malloc for newMessage\n");
char * newMessage = malloc(1024 * sizeof(char));
if (debug) printf("goto: handleEverything\n");
newMessage = handleEverything(message, Server, newMessage);
if (debug) printf("returnMessage:%s\n",newMessage);
strcpy(message,newMessage);
free(newMessage);
pthread_mutex_unlock(&mutex);
if (debug) printf("message = %s\n", message);
send(snew, message, sizeof(message), 0);
printf("End of threadFunction\n");
return;
}
/* -------------------------------------------
function: main
Function Body of Server
------------------------------------------- */
int main(int argc, char * argv[])
{
int sock, fromlength, outnum, i, socketNumber, snew;
bool cleanMode;
// Initialize Signal Handling
struct sigaction act;
act.sa_handler = sigint_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, 0);
// For correct number of arguments.
if (argc == 4)
{
// If "-n" parameter (cleanMode)
if (strcmp(argv[2], "-n") == 0)
{
// Get size + 1
cleanMode = true;
sscanf(argv[3],"%d",&serverSize);
serverSize += 1;
if (debug) printf("== Clean Mode Properly Initiated == \n");
if (debug) printf("serverSize: %d\n",serverSize);
if (debug) printf("Clean Mode Calloc\n");
Server = calloc(serverSize, sizeof(*Server));
int i = 0;
for (i; i < serverSize; i++) // Initialize allocated Memory
{
Server[i].line = i;
Server[i].type = 'p';
Server[i].bytes = 0;
strcpy(Server[i].string,"");
}
}
// If "-f" parameter (filemode)
else if (strcmp(argv[2], "-f") == 0)
{
// Read File
cleanMode = false;
readFile(argv[3]);
if (debug) printf("== Statefile Mode Properly Initiated == \n");
if (debug) printf("serverSize: %d\n",serverSize);
}
// Otherwise incorrect parameter.
else
{
printf("Incorrect Argument. \n");
printf("Usage: wbs279 pornumber {-n number | -f statefile}\n");
exit(1);
}
sscanf(argv[1],"%d",&socketNumber);
}
// Send Error for Incorrect Number of Arguments
if (argc != 4)
{
printf("Error: Incorrect Number of Input Arguments.\n");
printf("Usage: wbs279 portnumber {-n number | -f statefile}\n");
exit(1);
}
// == Do socket stuff ==
char tempmessage[1024], message[2048];
struct sockaddr_in master, from;
if (debug) printf("Assrt Socket\n");
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("Server: cannot open master socket");
exit (1);
}
master.sin_family = AF_INET;
master.sin_addr.s_addr = INADDR_ANY;
master.sin_port = htons (socketNumber);
if (bind (sock, (struct sockaddr*) &master, sizeof (master)))
{
perror ("Server: cannot bind master socket");
exit (1);
}
// == Done socket stuff ==
listen (sock, 5);
int threadNumber = 0;
while(1)
{
printf("But what about now.\n");
if (debug) printf("-- Wait for Input --\n");
printf("Enie, ");
fromlength = sizeof (from);
printf("Meanie, ");
snew = accept (sock, (struct sockaddr*) & from, & fromlength);
printf("Miney, ");
if (snew < 0)
{
perror ("Server: accept failed");
exit (1);
}
printf("Moe\n");
pthread_create(&thread[threadNumber],NULL,threadFunction(snew), &id[threadNumber]);
//printf("Can I join?!\n");
//pthread_join(thread[0],NULL);
//printf("Joined?!\n");
threadNumber++;
close (snew);
}
}
I'm also curious as to how exactly to let multiple clients use the server at once. Is how I've allocated the whiteboard structure data appropriate for this process?
I'm very sorry if these don't make any sense.
You seem to somehow expect this:
pthread_create(&thread[threadNumber],NULL,threadFunction(snew), &id[threadNumber]);
/* ... */
close (snew);
To make sense, while it clearly doesn't.
Instead of starting a thread that runs threadFunction, passing it snew, you call the thread function and pass the return value to pthread_create(), which will interpret it as a function pointer. This will break, especially considering that the thread function incorrectly ends with:
return;
This shouldn't compile, since it's declared to return void *.
Also assuming you managed to start the thread, passing it snew to use as its socket: then you immediately close that socket, causing any reference to it from the thread to be invalid!
Please note that pthread_create() does not block and wait for the thread to exit, that would be kind of ... pointless. It starts off the new thread to run in parallel with the main thread, so of course you can't yank the carpet away from under it.
This signal handler is completely unsafe:
void sigint_handler(int sig)
{
if (debug) printf("\nInduced SIGINT.\n");
FILE *fp;
fp=fopen("whiteboard.all","w");
int x=0;
for (x;x<serverSize;x++) // Loop Responsible for iterating all the whiteboard entries.
{
if (debug) printf("#%d%c%d\n%s\n",Server[x].line,Server[x].type,Server[x].bytes,Server[x].string);
fprintf(fp,"#%d%c%d\n%s\n",Server[x].line,Server[x].type,Server[x].bytes,Server[x].string);
}
if (debug) printf("All values stored.\n");
free(Server); // Free dynamically allocated memory
exit(1);
}
Per 2.4.3 Signal Actions of the POSIX standard (emphasis added):
The following table defines a set of functions that shall be
async-signal-safe. Therefore, applications can call them, without
restriction, from signal-catching functions. ...
[list of async-signal-safe functions]
Any function not in the above table may be unsafe with respect to signals. Implementations may make other interfaces
async-signal-safe. In the presence of signals, all functions defined
by this volume of POSIX.1-2008 shall behave as defined when called
from or interrupted by a signal-catching function, with the exception
that when a signal interrupts an unsafe function or equivalent
(such as the processing equivalent to exit() performed after a return
from the initial call to main()) and the signal-catching function
calls an unsafe function, the behavior is undefined. Additional
exceptions are specified in the descriptions of individual functions
such as longjmp().
Your signal handler invokes undefined behavior.

Resources