Segmentation fault - Socket Programming - C - c

I am trying to write an echo server\client model in C. My code compiles but throws a segmentation fault error at run-time [I believe on the server side process]. When testing in CLion debug environment, the server process is able to execute the accept() system call and enter into a a waiting state until a client connects. Therefore, I believe that the segmentation fault error happens after the client makes the connect() system call.
Here are the relevant snippets of code (only the last part - not full program):
/* [6] LISTEN FOR CONNECTIONS ON BOUND SOCKET===================================================================== */
struct sockaddr_storage ample; /* from Beej Guide 5.6 accept() */
socklen_t ample_sz = sizeof(ample);
fd_activeSock = accept(fd_listenSock, (struct sockaddr *)&established_SERV_param, &ample_sz);
if (fd_activeSock == -1) /* Error checking */
{
fprintf(stderr, "\nNo forum for communication...\nTERMINATING PROCESS");
exit(EXIT_FAILURE);
}
printf("\nCommunication Established! What's your sign??");
freeaddrinfo(established_SERV_param); /* free up memory */
/* [7] ACCEPT A CONNECTION (BLOCKING)============================================================================= */
/* MAIN LOOP====================================================================================================== */
while(1)
{
bzero(msg_incoming, 16);
recv(fd_activeSock, msg_incoming, 16, 0);
printf("%s", msg_incoming);
send(fd_activeSock, msg_incoming, 16, 0);
}
When I run both programs in separate terminals (server process first, of course), the last print statement that runs before the error is:
printf("\nCommunication Established! What's your sign??");
The error is output to the server terminal. There is a core dump; for future issues, could someone suggest a beginners tutorial on combing through core dump files. Also, I have run the code with the freeaddrinfo() call commented out and still get a segmentation fault error so I do not believe that this is the issue. Why run it at all? I do not want memory leaks. Thank you for your help.

recv() does not explicitly place a null terminator at the end of the buffer, but printf() expects one.
In the statements:
bzero(msg_incoming, 16);
recv(fd_activeSock, msg_incoming, 16, 0);
printf("%s", msg_incoming);
Although msg_incoming has been zeroed, when it is populated in the recv call, if all 16 elements are populated, there is no guaranteed that the last element of the array was populated with '\0', leaving the buffer as a non-null terminated array. If that happens, A segfault is likely when printf() is called. Or worse, a segfault may not occur, leading you to believe your code works fine. (AKA undefined behavior)
The fix is to check the return value of recv():
ssize_t bytes = recv(fd_activeSock, msg_incoming, 16, 0);
if(bytes <= 0)
{
//handle error/end of message condition
}
else
{
msg_incoming[bytes] = '\0';
printf("%s", msg_incoming);
}
Additional material on Reading data with a socket.

freeaddrinfo(established_SERV_param)
Should be called when established_SERV_param is obtained by getaddrinfo. Here established_SERV_param is probably a stack variable. Hence, you are trying to free a pointer to stack variable.
Umm something is wrong in your program. Since, freeaddrinfo expects a pointer but it is a variable since you use & in call to accept. Removing the call to freeaddrinfo may fix it.
If above is not enough then it is important to see how msg_incoming is defined/allocated. It should not be a const char array or initialised by a string literal making it a const. If it is a pointer it should be adequately allocated memory using malloc.
Analysing core dump:
Compile your code with debug On and optimisation Off
gcc -g -O0
Then open the core file in gdb as
gdb <executable> <core file>
(gdb) bt
Above, bt will show you the back trace where the program crashed. You can go the function it crashed by command fr 0 and print some variables. A tutorial for gdb can found here

Related

Why the C recv() function in my self-write dll stocked even broke my Labview program if I didn't keep sending data from server.c via TCP socket

I want to write a simple TCP socket Client dll base on C Language
import to my Labview program.
I defined three functions in my dll as follow:
char* DLL_EXPORT TCPSocket(int input); //open socket
void DLL_EXPORT closeSocket(void); //close socket
int DLL_EXPORT pulse(int trig); //waiting incoming signal from server.c and return a value
the first two of them worked great,
But the last one always blocks and broke my Labview if it didn't receive anything.
The main function I want is that waiting for a trigger signal from my Server,
So this must exist a waiting time interval, and that is why it caused my Labview to crashed.
int DLL_EXPORT pulse(int trig)
{
int Text;
int pass = 0, rx;
send(sock,(char *)&trig,sizeof(trig),0);
rx = recv(sock,(char *)&Text,64,0);
while(1)
{
if(rx <= 0)
{
pass = 0;
break;
}
else if(rx > 0)
{
pass = Text;
break;
}
return pass;
}
return pass;
}
Is it possible to create a dll for Labview just to waiting for an output finished signal and plz don't
crash my LabVIEW?
enter image description here
There are several reasons why LV might crash when calling a DLL. For example a segmentation fault or any other crash inside the DLL.
With int Text;, you allocate 4 bytes of memory to store the incoming data, but you allow the recv() function to receive up to 64 bytes. If it received more than 4 bytes, it writes data beyond the memory boundary of Text, and this can lead to a segmentation fault. Just allow up to 4 bytes (or sizeof(Text)) to be read.
By the way: If you receive a single byte like A (or 0x41), it will be placed in the most significant byte of Text, so Text will be 0x41000000=‭1090519040‬. But only if Text were 0 before. You do not initialize it, which means it could contain any random value.
Next, what is sock? It is not declared anywhere in your code. (It is, otherwise it would not compile) If sock is not initialized correctly, recv() might crash.
Finally, the current functionality can be achieved within LabVIEW. Is there any reason for using a DLL?

Assert calls segmentation fault

I'd written some sort of basic multi-threading library. So, for each thread, I'd a context (ucontext_t). In one of my test programs, I put an assert which failed. Instead of aborting with a line number, it threw a segmentation fault. I then checked and saw the stack size of my context was 8192. When I increased it to 16394, the assert failure worked as expected.
Can you someone tell me as to how assert works internally and why would it use up so many bytes? I believe 8192 is a fairly large size for my context.
This is how my thread is created
MyThread *temp;
temp=malloc(sizeof(MyThread_t));
ucontext_t tempContext;
if (getcontext(&tempContext) == -1)
temp->ThreadId = 0;
tempContext.uc_stack.ss_sp = (char *)malloc(SIZE_STACK*sizeof(char));;
tempContext.uc_stack.ss_size = SIZE_STACK*sizeof(char);
tempContext.uc_link = NULL;
makecontext(&tempContext,(void(*)(void))start_funct,1, args);
And my test function has it this way.
T = MyThreadCreate(t0, (void *)n2);
re=MyThreadJoin(T);
printf("%d\n",re);
assert(re==-1);
re value is 0. When my SIZE_STACK is 8192, I get a seg fault. When its increased to 16384, it is a proper abort as expected from assert.
The implementation of assert is platform dependent.

malloc works, cudaHostAlloc segfaults?

I am new to CUDA and I want to use cudaHostAlloc. I was able to isolate my problem to this following code. Using malloc for host allocation works, using cudaHostAlloc results in a segfault, possibly because the area allocated is invalid? When I dump the pointer in both cases it is not null, so cudaHostAlloc returns something...
works
in_h = (int*) malloc(length*sizeof(int)); //works
for (int i = 0;i<length;i++)
in_h[i]=2;
doesn't work
cudaHostAlloc((void**)&in_h,length*sizeof(int),cudaHostAllocDefault);
for (int i = 0;i<length;i++)
in_h[i]=2; //segfaults
Standalone Code
#include <stdio.h>
void checkDevice()
{
cudaDeviceProp info;
int deviceName;
cudaGetDevice(&deviceName);
cudaGetDeviceProperties(&info,deviceName);
if (!info.deviceOverlap)
{
printf("Compute device can't use streams and should be discarded.");
exit(EXIT_FAILURE);
}
}
int main()
{
checkDevice();
int *in_h;
const int length = 10000;
cudaHostAlloc((void**)&in_h,length*sizeof(int),cudaHostAllocDefault);
printf("segfault comming %d\n",in_h);
for (int i = 0;i<length;i++)
{
in_h[i]=2; // Segfaults here
}
return EXIT_SUCCESS;
}
~
Invocation
[id129]$ nvcc fun.cu
[id129]$ ./a.out
segfault comming 327641824
Segmentation fault (core dumped)
Details
Program is run in interactive mode on a cluster. I was told that an invocation of the program from the compute node pushes it to the cluster. Have not had any trouble with other home made toy cuda codes.
Edit
cudaError_t err = cudaHostAlloc((void**)&in_h,length*sizeof(int),cudaHostAllocDefault);
printf("Error status is %s\n",cudaGetErrorString(err));
gives driver error...
Error status is CUDA driver version is insufficient for CUDA runtime version
Always check for Errors. It is likely that cudaHostAlloc is failing to allocate any memory. If it fails, you are not bailing but are rather writing to unallocated address space. When using malloc it allocates memory as requested and does not fail. But there are cases when malloc may result in failures as well, so it is best to do checks on the pointer before writing into it.
For future, it may be best to do something like this
int *ptr = NULL;
// Allocate using cudaHostAlloc or malloc
// If using cudaHostAlloc check for success
if (!ptr) ERROR_OUT();
// Write to this memory
EDIT (Response to edit in the question)
The error message indicates you have an older driver compared to the toolkit. If you do not want to be stuck for a while, try to download an older version of cuda toolkit that is compatible with your driver. You can install it in your user account and use its nvcc + libraries for temporarily.
Your segfault is not caused by the writes to the block of memory allocated by cudaHostAlloc, but rather from trying to 'free' an address returned from cudaHostAlloc. I was able to reproduce your problem using the code you provided, but replacing free with cudaFreeHost fixed the segfault for me.
cudaFreeHost

Sending a message from server to client

I am implementing both server and client side of a simple file download program. Client side requests file names from the server with get command, and server responses quickly. While server writes to the socket, clients reads the socket and prints out the buffer. After that time, program starts not to interpret my commands unless I press 'Enter' twice. (You can see it from Shell output below)
After debugging, I found out that it is because of the buffer size. While server writing to the socket; everything works properly if I use a small buffer size. But if I use a larger buffer size such as 1024, that problem occurs. How can I get rid of this issue?
#define F_BUFF_SIZE 1024
On server side:
/* ... */
if(!strcmp(buffer, "list\n")) {
char buff[F_BUFF_SIZE];
bzero(buff, F_BUFF_SIZE);
pt_ret = pthread_create(&thread_id, NULL, getfiles, (void*) buff);
pthread_join(thread_id, pt_ret);
n = write(sock, buff, F_BUFF_SIZE);
/* ... */
On client side:
/* ... */
char buffer[F_BUFF_SIZE];
bzero(buffer, F_BUFF_SIZE);
n = read(b_sock, buffer, F_BUFF_SIZE - 1);
if (n < 0) {
#ifdef _DEBUG_
fprintf(stderr, "Error: Could not read from the socket.\n");
#endif
return 0;
}
fputs(buffer, stdout);
/* ... */
Shell:
Opening socket: OK!
Connecting: OK!
# list
client
project1.mk
cs342.workspace
client.c
project1.project
cs342.workspace.session
server
cs342_wsp.mk
server.c
cs342.tags
# get
# take
get
# take
Unknown command.
...
There is no magic to having a smaller buffer size, this is just exposing that you have an error elsewhere. Joerg's comment is an important point - you need to be reading the same amount of data that you are writing. I'm wondering if there's also an issue with how you populate buff. You need to make sure that you are not overrunning the end of the buffer, or forgetting to add a null terminator to the end of the string.
By the way, it is important to read the size - 1; you're correct to do this since read won't append a null terminator to a string. You just need to be sure that you're writing that amount because otherwise there can be problems.
You must have some issue along these lines - this would explain why changing the size avoids the problem because problems like this are only exposed when the numbers line up perfectly. Running the program in valgrind may expose the issue (look for invalid write errors).
#ahmet, your useful question lead me to research a little bit. If you read a little bit on this paper you will have a better idea of what you are dealing with and then you will be able to determine the best buffer size in your situation.
As you may know, values like that should always be part of the settings of the application, so don't scramble those values inside the code.
Also, here are good advices on how to figure buffer size, hope that helps,

Does valgrind track memory initialization through drivers?

valgrind is reporting uninitialized memory errors from code like this:
unsigned char buf[100];
struct driver_command cmd;
cmd.len = sizeof(buf);
cmd.buf = buf;
ioctl(my_driver_fd, READ, &cmd);
for(i = 0; i < sizeof(buf); i++)
{
foo(buf[i]); /* <<--- uninit use error from valgrind */
}
If I memset() the buf before the driver call, the error goes away.
Can valgrind detect whether the linux driver is properly writing to the buffer? (I looked at the driver code, and it seems to be correct, but maybe I'm missing something.)
Or does it just pass the driver call through and has no way of knowing that the buffer has been written inside the kernel?
Thanks.
Valgrind obviously can't trace execution into the kernel, but it does know the visible semantics of most system calls. But ioctl is too unpredictable. If you had coded your driver so that that was a read call, it would get it right. That's better practice anyway.

Resources