Related
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.
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.
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 );
}
}
}
I wrote a C server that should send to a client the file it requested through the XDR library, using the buffer paradigm. The program uses a custom struct.
enum tagtype {
GET = 0,
OK = 1,
QUIT = 2,
ERR = 3
};
struct file {
opaque contents<>;
unsigned int last_mod_time;
};
union message switch (tagtype tag) {
case GET:
string filename<256>;
case OK:
struct file fdata;
case QUIT:
void;
case ERR:
void;
};
This is the core part of the XDR server.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <rpc/xdr.h>
#include "xdr_file.h"
//main() and call to manage_clixrequest()
int manage_clixrequest(int clisocket_fd) {
FILE *req_file;
struct stat metadata;
char rcv_message[CHUNK_SIZE] = "";
char *buffer, buffer2[2048];
size_t nbytes = 0;
int sent, n;
XDR xdrs_r, xdrs_w; // Pointer to XDR streams
message msg, send_msg;
/* Create codification stream */
xdrmem_create(&xdrs_r, rcv_message, sizeof(rcv_message), XDR_DECODE);
memset(&msg, 0, sizeof(msg));
memset(&send_msg, 0, sizeof(send_msg));
msg.tag = ERR;
msg.message_u.filename = NULL;
msg.message_u.fdata.contents.contents_len = 0;
msg.message_u.fdata.contents.contents_val = NULL;
msg.message_u.fdata.last_mod_time = 0;
/* The server waits for data */
n = recv(clisocket_fd, rcv_message, sizeof(rcv_message), 0);
/* Check if the server received some data */
if (n < 0) {
printf("Errno %d in recv(): %s\n", errno, strerror(errno));
}
if(!xdr_message(&xdrs_r, &msg)){
printf("Error in xdr_message()\n");
return -1;
}
xdr_destroy(&xdrs_r);
/* For a GET message the function extracts the filename
* and send the corresponding file to the client */
if (msg.tag == GET) {
req_file = fopen(msg.message_u.filename, "rb");
/* Check if the file is valid */
if (req_file == NULL) {
if (errno == 2){
xdrmem_create(&xdrs_w, buffer, sizeof(buffer), XDR_ENCODE);
/* The requested file does not exist, so an error message is sent
* and the connection is going to be shutdown */
send_msg.tag = ERR;
if(!xdr_message(&xdrs_w, &send_msg)){
printf("Error in xdr_message()\n");
return -1;
}
sent = send(clisocket_fd, buffer, sizeof(buffer), 0);
/* Check if the server sent the data */
if (sent < 0) {
printf("Errno %d in send(): %s\n", errno, strerror(errno));
}
xdr_destroy(&xdrs_r);
xdr_destroy(&xdrs_w);
return 0;
} else {
printf("Errno %d in fopen(): %s\n", errno, strerror(errno));
return -1;
}
}
/* Check if the file metadata are correctly retrieved */
if (fstat(fileno(req_file), &metadata) < 0) {
printf("Errno %d in fstat(): %s\n", errno, strerror(errno));
return -1;
}
/* File is read and memorized in a temporary buffer */
buffer = (char *) malloc(sizeof(char)*metadata.st_size);
memset(buffer, 0, metadata.st_size);
nbytes = fread(buffer, sizeof(char), metadata.st_size, req_file);
memset(buffer2, 0, sizeof(buffer2));
/* Create codification stream */
xdrmem_create(&xdrs_w, buffer2, sizeof(buffer2), XDR_ENCODE);
/* This is the beginning of the message for the client
* when the file is going to be sent */
send_msg.tag = OK;
/* The file size and last modification time are retrieved */
send_msg.message_u.fdata.contents.contents_len= metadata.st_size;
send_msg.message_u.fdata.last_mod_time = metadata.st_mtime;
send_msg.message_u.filename = msg.message_u.filename;
send_msg.message_u.fdata.contents.contents_val = buffer;
if(!xdr_message(&xdrs_w, &send_msg)){
printf("Error in xdr_message()\n");
return -1;
}
/* The XDR struct is sent with the send() function */
sent = send(clisocket_fd, buffer2, nbytes, 0);
/* Check if the server sent the data */
if (sent < 0) {
printf("Errno %d in send(): %s\n", errno, strerror(errno));
return -1;
}
free(buffer);
xdr_destroy(&xdrs_w);
} else if (msg.tag == QUIT) {
/* The client asked to shutdown the connection.
* Unused if the client itself closes the connection */
return 0;
} else {
/* The client sent a request with a not expected tag, so an error message is sent
* and the connection is going to be shutdown*/
xdrmem_create(&xdrs_w, buffer, sizeof(buffer), XDR_ENCODE);
send_msg.tag = ERR;
if(!xdr_message(&xdrs_w, &send_msg)){
printf("Errno %d in xdr_message(): %s\n", errno, strerror(errno));
return -1;
}
sent = send(clisocket_fd, buffer, sizeof(buffer), 0);
/* Check if the server sent the data */
if (sent < 0) {
printf("Errno %d in send(): %s\n", errno, strerror(errno));
}
xdr_destroy(&xdrs_w);
return 0;
}
return 1;
}
Unfortunately the encodification of the message causes a segmentation fault.
Program received signal SIGSEGV, Segmentation fault.
xdrmem_putlong (xdrs=0x7fffffffd050, lp=0x7fffffffcf58) at xdr_mem.c:124
124 xdr_mem.c: No such file or directory.
I checked the program with GDB and I obtained this backtrace
(gdb) backtrace
#0 xdrmem_putlong (xdrs=0x7fffffffd050, lp=0x7fffffffcf58)
at xdr_mem.c:124
#1 0x00007ffff7b4d99c in __GI_xdr_enum (xdrs=<optimized out>,
ep=0x7fffffffd000) at xdr.c:500
#2 0x000055555555617e in xdr_tagtype (xdrs=0x7fffffffd050,
objp=0x7fffffffd000) at xdr_file.c:13
#3 0x0000555555556214 in xdr_message (xdrs=0x7fffffffd050,
objp=0x7fffffffd000) at xdr_file.c:35
#4 0x0000555555555847 in manage_clixrequest (clisocket_fd=4)
at server3-4.c:273
#5 0x00005555555552a6 in main (argc=3, argv=0x7fffffffdd78)
at server3-4.c:129
where manage_clixrequest(socket_fd) is the function I wrote. I don't know if I am using badly the XDR library, or if I am forgetting to include something so that the xdr_mem.c is not linked correctly. Do you have any ideas/tips?
EDIT
I reported the whole server function and the xdr_file.c.
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "xdr_file.h"
bool_t
xdr_tagtype (XDR *xdrs, tagtype *objp)
{
register int32_t *buf;
if (!xdr_enum (xdrs, (enum_t *) objp))
return FALSE;
return TRUE;
}
bool_t
xdr_file (XDR *xdrs, file *objp)
{
register int32_t *buf;
if (!xdr_bytes (xdrs, (char **)&objp->contents.contents_val, (u_int *) &objp->contents.contents_len, ~0))
return FALSE;
if (!xdr_u_int (xdrs, &objp->last_mod_time))
return FALSE;
return TRUE;
}
bool_t
xdr_message (XDR *xdrs, message *objp)
{
register int32_t *buf;
if (!xdr_tagtype (xdrs, &objp->tag))
return FALSE;
switch (objp->tag) {
case GET:
if (!xdr_string (xdrs, &objp->message_u.filename, 256))
return FALSE;
break;
case OK:
if (!xdr_file (xdrs, &objp->message_u.fdata))
return FALSE;
break;
case QUIT:
break;
case ERR:
break;
default:
return FALSE;
}
return TRUE;
}
I found out that I used the same buffer to memorize the file bytes and to create the XDR stream, that is an error. Now there is no segmentation fault and the XDR struct message is correctly filled, but now the call to the generated function xdr_bytes() returns false and the encodification still fails.
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.