Segmentation fault in Thread pool - linux

i am creating a bluetooth based server program in Bluez which basically handles connections from multiple devices. I have constructed two threads; one to scan the remote devices and another to connect with the devices that are broadcasting the service. Again, a separate thread is extracted from a thread pool for each of the newly connected devices which will then communicate with the server over a RFCOMM channel.
After establishing connection with a remote device, the server will send commands to the remote bluetooth device. Once the remote device a reply, the server reads that reply and stores it.
Now, the problem is whenever I get a reply back from the device the program crashes stating a "segmentation fault". Can anyone tell me a possible cause for this. The part of the code that does this is given here.
void startCommunication( int newSocket )
{
char buf[MODZ_MAX_DATA_SIZE] = "\0";
char previousData[ MODZ_MAX_DATA_SIZE ] = "\0";
time_t recvTime, prevRecvTime;
char dataToBeSent[ 4*MODZ_MAX_DATA_SIZE ] = "\0";
char *result;
if( sendDataToClient( newSocket, CMD_SEND) == EXT_ERROR ) //send acknowledgement first
printf("Couldn;t send ack\n");
else { printf("Date send woot! woot! %s\n", CMD_SEND); }
memset( buf, '0', sizeof(buf) );
while( 1 ){
recvTime = time( ( time_t * )0 );
if( readDataFromClient( newSocket, buf ) == EXT_ERROR ){
printf( "Read Error\n" );
break;
}
printf( "Data received = %s\n", buf );
strcpy( previousData, buf );
// store the data in a file and send to web
// check if the web has any data to send and if there is then send
result = "here we update the challenge";
strcpy( dataToBeSent, result );
free( result );
result = NULL;
//strcpy( buf, "We will soon update the database" );
if( sendDataToClient( newSocket, dataToBeSent ) == EXT_ERROR ){
break;
}
}
close( newSocket );
if( result != NULL ){
free( result );
}
printf( "\n****************Device disconnected***************\n" );
}

One obvious problem:
result = "here we update the challenge";
strcpy( dataToBeSent, result );
free( result );
You are freeing a pointer that was not allocated with malloc. That could well cause a segmentation fault.
In the future, try to use gdb to figure out exactly where your program crashes.

Related

Fail to unmount a block device within kernel sources

I'm trying to check if a file on a jffs2 fs exist from a kernel space. I have a Barrier Breaker OpenWrt with a 3.10.14 Linux kernel. (There's an MTD subsystem in use, so I have pseudo block devices for partitions on a NAND flash (/dev/mtdblock1, ...12).)
(I'm implementing some upgrading logic which requires keeping some state between reboots, to store this state, I use the file.)
To check a file existence I just try to open the file (without an O_CREAT flag) and make a decision based on a result of opening. I use the next article about opening a file from within kernel: Read/write files within a Linux kernel module.
I'm able to check a file existence using this approach, but this file is placed not on a rootfs partition, so I have to mount that partition before I can open the file on it.
I'm able to mount the partition, open file (to check it existence) and close it, if it was opened, but failed to un-mount it: I got an error -16: EBUSY which, as I guess, means that someone else keep using this block device/mount point. So a question who can keep a reference on it?
I think it's a bad idea, but just to test, I tried to un-mount forcibly with an MNT_FORCE, but, as this article https://linux.die.net/man/2/umount states that this option only for NFS fs, nothing changed.
Here's a code:
/* lool at https://stackoverflow.com/questions/1184274/read-write-files-within-a-linux-kernel-module */
static struct file *file_open( const char *path, int flags, int rights )
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs( get_ds() );
filp = filp_open( path, flags, rights );
set_fs( oldfs );
if( IS_ERR( filp ) )
{
err = PTR_ERR( filp );
return NULL;
}
return filp;
}
bool need_to_switch_to_me_upgrade_mode( void )
{
struct file* me_upgrade_finished_file;
dev_t me_upgrade_dev;
char full_name[256] = { 0 };
bool result;
int err;
const char* me_upgrade_dir = "/me_upgrade";
const char* me_upgrade_dev_name = "/dev/me_upgrade";
const char* me_upgrade_finished_flag = "/etc/me_upgrade_finished";
// /dev/mtdblock6
const char* me_upgrade_finished_flag_partition = "/dev/mtdblock" str( RECOVERY_ROOTFS_DATA_MTD_PART_NUM );
err = sys_mkdir( (const char __user __force *) me_upgrade_dir, 0700 );
if( err < 0 )
panic( "fail to mkdir %s\n", me_upgrade_dir );
me_upgrade_dev = name_to_dev_t( me_upgrade_finished_flag_partition );
err = create_dev( me_upgrade_dev_name, me_upgrade_dev );
if( err < 0 )
panic( "fail to create_dev %s\n", me_upgrade_dev_name );
err = sys_mount( me_upgrade_dev_name, me_upgrade_dir, "jffs2", MS_SILENT, NULL );
if( err < 0 )
panic( "fail to mount %s on to %s, err: %d\n", me_upgrade_dev_name, me_upgrade_dir, err );
strlcat( full_name, me_upgrade_dir, sizeof( full_name ) );
strlcat( full_name, me_upgrade_finished_flag, sizeof( full_name ) );
me_upgrade_finished_file = file_open( full_name, O_RDONLY, 0 );
if( !me_upgrade_finished_file )
{
printk( "fail to open a %s file\n", full_name );
result = true;
}
else
{
printk( "success to open a file\n" );
result = false;
}
if( me_upgrade_finished_file )
{
err = filp_close( me_upgrade_finished_file, NULL );
printk( "filp_close returned: %d\n", err );
}
err = sys_umount( me_upgrade_dir, MNT_DETACH );
printk( "sys_umount returned: %d\n", err );
sys_unlink( me_upgrade_dev_name ); // destroy_dev( me_upgrade_dev_name );
sys_rmdir( me_upgrade_dir );
return result;
}
This code is called from a kernel_init_freeable function (init/main.c) after we have MTD subsystem initialized (after do_basic_setup() and before a rootfs gets mounted).
So the questions are:
who can keep using a block device/mount point after I closed a file?
is any other ways to check if file exist from within kernel?
I have a second option, just to place my state in a partition without any fs, and check it by performing a raw access to the flash memory, but this approach will require significant changes to user code I have now, so I'm trying to avoid it...
P.S. I tried to change a call to file_open/filp_close by sys_open/sys_close (with the same arguments), but nothing changed...

Cant pass different strings to multiple threads

I have a function that will generate multiple threads and i pass to them a different string every time, but it seems that the threads have the same string. The strings are coming from a socket. Here is the code:
pthread_t *MirrorManager;
MirrorManager = malloc(sizeof(pthread_t)*th_size);
if( MirrorManager == NULL ) { perror("malloc"); exit(1); }
/* -------------------------------------- */
int th_num = 0;
while( true )
{
received = 0;
/* Read the desired readable size */
if( read(newsock, &size, sizeof(size)) < 0 )
{ perror("Read"); exit(1); }
/* Read all data */
while( received < size )
{
if( (nread = read(newsock, buffer + received, size - received)) < 0 )
{ perror("Read"); exit(1); }
received += nread;
}
if( strcmp(buffer, "end") == 0 ) { break; }
printf("Received string: %s\n",buffer);
/* Create thread */
strcpy(th_str, buffer);
if( (err = pthread_create(&MirrorManager[th_num], NULL, thread_start, (void*) th_str)) == true )
{ show_error("pthread_create", err); }
/* Take next thread */
th_num++;
}
Here i generate two threads. The two threads have the same string, actually this string is the last string that will come out of the socket. Why this is happening and how can i prevent this? Please help i have stuck here for a few days now.
You should post the complete code.
Given what you have posted, it looks like your issue is that all of your threads share the same parameter th_str:
pthread_create(&MirrorManager[th_num], NULL, thread_start, (void*) th_str))
Instead you should be allocating a separate th_str for each thread, as you're passing a pointer to it for each thread, rather than the string itself.
th_str = malloc(strlen(buffer));
strcpy(th_str, buffer);
And then be sure to have each thread free the pointer that was passed into it.
PS: I'd strongly recommend using strncmp and strncpy on all data from your socket.

waveOutOpen(), waveOutWrite() gives my thread undocumented message 1024

The sound output functions are giving me unexpected messages. Is this a sign I'm doing something wrong? If so what? Otherwise is there a good source that explains what these messages might be?
waveOutOpen() gives me message 955 MM_WOM_OPEN as documented, followed by an undocumented 1024 (possibly DDM_SETFMT, DM_GETDEFID, NIN_SELECT, TBM_GETPOS, WM_PSD_PAGESETUPDLG, WM_USER, according to https://wiki.winehq.org/List_Of_Windows_Messages).
In main thread:
hAudioOut = CreateThread( 0, 0, AudioOutThreadProc, this, 0, &dwAudioOutId );
if( !hAudioOut ) {
AKS( AKSWarn, "Audio Out CreateThread() fail" );
return;
}
In the resulting audio thread:
static DWORD WINAPI AudioOutThreadProc( LPVOID lpParameter ) {
Interpreter* pinterp = (Interpreter *) lpParameter;
WAVEFORMATEX waveFormat;
waveFormat.cbSize = sizeof(waveFormat);
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 1;
waveFormat.nSamplesPerSec = (int) dFreqEval;
waveFormat.wBitsPerSample = iOutputBits;
waveFormat.nBlockAlign = waveFormat.nChannels *
waveFormat.wBitsPerSample / 8;
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec *
waveFormat.nBlockAlign;
MMRESULT openRes = waveOutOpen( &waveOut, WAVE_MAPPER, &waveFormat,
(DWORD_PTR) dwAudioOutId, (DWORD_PTR) this,
CALLBACK_THREAD /*| WAVE_FORMAT_DIRECT*/ );
if ( openRes != MMSYSERR_NOERROR )
Log( "waveOutOpen() = %d", openRes );
MSG msg;
int iRV;
while ( iRV = GetMessage( &msg, 0, 0, 0 ) ) {
Log( "got message %d", msg.message );
// Is the main thread asking us to stop?
if ( pinterp->bStop ) {
Log( "AudioInThreadProc(): bStop" );
return EXIT_SUCCESS;
}
// Did we get an error?
if ( iRV == -1 ) {
Log( "GetMessage() = -1: %d", GetLastError() );
abort();
}
// Did we get an expected message? (Only one expected,
// which tells us its time to write more data.)
if ( msg.message == WOM_DONE )
pinterp->Write();
// Anything else--log it.
else
Log( "got unknown message %d", msg.message );
}
Log( "AudioInThreadProc(): GetMessage = return" );
return msg.wParam;
}
waveOutWrite() isn't documented to give any messages, but is giving me message 1024 as well.

Winsock threaded server does not work well when multiple clients connect?

I have a server that spawns a thread for each client that connects to it. The thread then deals with receiving/sending data to the client. Here is my server code:
//////////////
// START //
/////////////
while( 1 )
{
if( listen(serverSocket, SOMAXCONN) == SOCKET_ERROR )
{
printf( "Listen failed with error: %ld\n", WSAGetLastError() );
break;
}
/*
* wait for clients...
*/
clientSocket = accept(serverSocket,
(struct sockaddr *)&clientSockAddr,
&clientSockAddrLen);
if( clientSocket == INVALID_SOCKET )
{
printf("%d:accept failed\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("Client accepted: IP: %s PORT: %d\n",
inet_ntoa(clientSockAddr.sin_addr),
clientSockAddr.sin_port );
THREADDATA threadData = { clientSocket };
sprintf_s(threadData.ip, "%s", inet_ntoa(clientSockAddr.sin_addr));
// spawn a thread for each client
hthread = CreateThread(
NULL, // don't inherit handle
0, // use default size for the executable
processClient,
(pTHREADDATA)&threadData, // thread data
0, // run right away
&threadId );
}
And here is what my thread function looks like:
/*
called by thread for each client
*/
DWORD WINAPI processClient(LPVOID lpParam)
{
int numBytesRecvd = 0,
numBytesSent = 0,
index = 0,
nLeft = SIZE,
TOTAL = SIZE;
char buff[SIZE];
int run = 1;
char msg[MSG_SIZE];
pTHREADDATA td = (pTHREADDATA)lpParam;
/* keep processing client */
while (run)
{
memset(buff, 0, SIZE);
numBytesRecvd = recv(td->clientSocket, buff, nLeft, 0);
/* CLIENT EXITED */
if( !strcmp(buff, "exit") )
{
printf("Client exited!\n");
run = 0;
}
if( numBytesRecvd > 0 )
{
printf("< %s\n", buff);
}
if (numBytesRecvd == 0)
{
printf("Client closed!\n");
run = 0;
}
if( numBytesRecvd == SOCKET_ERROR )
{
printf("%d:Recieve error!\n", WSAGetLastError());
run = 0;
}
}
closesocket(td->clientSocket);
ExitThread(0);
return 0;
}
Issue:
So I start the server and the client, say client1 (from command prompt in win 7), everything is fine. When I type something at the client1 terminal, it is printed at the server terminal.
Now I launch another client, client2, it gets connected to the server and whatever I type gets displayed at the server, but now when I type something at client1 it doesn't get displayed at the server terminal.
So basically every time I start a new client, only that client can talk to the server, the old clients cannot!!! But I thought the thread will keep handling each client? Or is it that cmd prompt in windows is not thread safe?
I can see two probable issues here : 1) You are passing threadData on the stack to a different thread. You should be allocating it on the heap and then pass it to the thread. 2)I think you are not assigning clientSocket correctly to threadData, shouldnt you be assigning to a member of the structure threadData?

Windows named pipe used in service not working

I am using windows named pipe example. When I run sample programs to create pipe, write something and receive it in client program everything is just fine. When I move client code into dll, which runs in windows service it just won't receive sent bytes.
Server's code is as follows:
ThreadParams * params = reinterpret_cast<ThreadParams*>(args);
CString * connectionString = params->connectString;
HANDLE hPipe;
DWORD dwBytesRead;
TCHAR buf[1024];
int len;
hPipe = CreateNamedPipe(PIPE_NAME, // Name
PIPE_ACCESS_OUTBOUND | WRITE_OWNER, // OpenMode
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, // PipeMode
2, // MaxInstances
1024, // OutBufferSize
1024, // InBuffersize
2000, // TimeOut
NULL); // Security
if (hPipe == INVALID_HANDLE_VALUE)
{
Globals::WriteLog("Could not create the pipe",1);
exit(1);
}
Globals::WriteLog("connect...",1);
ConnectNamedPipe(hPipe, NULL);
Globals::WriteLog("...connected",1);
swprintf(buf, connectionString->GetBuffer());
len = wcslen(buf);
if (!WriteFile(hPipe, buf, len*sizeof(TCHAR), &dwBytesRead, NULL))
Globals::WriteLog("WriteFile failed",1);
else
wprintf(L"written %d bytes\n",dwBytesRead);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
And client:
CString finalResult = _T("");
HANDLE hOut = INVALID_HANDLE_VALUE;
TCHAR buf[1024];
DWORD len;
DWORD dwWritten;
Global::WriteLog("pwrite: waiting for the pipe...",1);
if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0)
{
Global::WriteLog("WaitNamedPipe failed. error=%d",1,GetLastError());
goto cleanup;
}
Global::WriteLog("the pipe is ready",1);
hOut = CreateFile(PIPE_NAME,
GENERIC_READ,
0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hOut == INVALID_HANDLE_VALUE)
{
Global::WriteLog("CreateFile failed with error %d",1,GetLastError());
goto cleanup;
}
Global::WriteLog("Opened the pipe",1);
for (;;)
{
if (!ReadFile(hOut, buf, sizeof(buf), &dwWritten, NULL))
{
Global::WriteLog("ReadFile failed -- probably EOF. Read %d bytes.",1,dwWritten);
goto cleanup;
}
else
break;
}
finalResult = CString(buf);
Global::WriteLog("String from pipe:%S",1,buf);
cleanup:
if(hOut != INVALID_HANDLE_VALUE)
CloseHandle(hOut);
Server's code runs in a thread if that changes anything (I've tested it with this thread version in sample program and there was no problem with this).
Why does it not work?
Thanks in advance
Okay, it seems I figured it out. It seems I didn't understood documentation properly.
At server's side WriteFile function doesn't block until the string is read. My program simply wrote data and then closed handle - pipe. Client didn't catch the message and threw error stating that there is no process on the other side of pipe.
Also from client I removed for(;;) loop.
To wait for read operation on client side to complete I added
FlushFileBuffers(hPipe);
after successful write operation.
Hope that help somebody

Resources