Xlib Muti-thread program only works under strace - pthreads

I'm writing a muti-thread program using xlib, pthread and cairo.
This program create a thread in order to draw ten points after a click event.
The problem is:
After the program drew three points, it got crashed and xlib complaint
X Error of failed request: BadRequest (invalid request code or no such operation)
Major opcode of failed request: 0 ()
Serial number of failed request: 67
Current serial number in output stream: 97
However, it can work properly when I'm using strace like "strace ./a.out".
Here's my code-clips:
void *draw_point(void *arg) { //paint random-postion point
int i = 0;
int seed;
double x ,y;
srand(seed);
cairo_set_source_rgba (cairo, 1, 0.2, 0.2, 0.6);
for(i = 0; i< 10; i++) {
x = rand() % 200;
y = rand() % 200;
if(candraw) {
cairo_arc (cairo, x, y, 10.0, 0, 2*M_PI);
cairo_fill (cairo);
}
hasdraw = true;
sleep(1);
}
return NULL;
}
bool win_main(void)
{
int clickx = 0, clicky = 0;
unsigned long valuemask;
XEvent event;
valuemask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask;
XSelectInput(display, win, valuemask);
pthread_t thread;
while (1) {
while (XPending(display) == 0) {
candraw = true;
if(hasdraw)
XFlush(display);
candraw = false;
}
XNextEvent(display, &event);
candraw = false;
switch (event.type) {
case MotionNotify:
//...
break;
case ButtonPress:
clickx = event.xbutton.x;
clicky = event.xbutton.y;
if(clicky < 50)
pthread_create(&thread, NULL, draw_point, NULL);
break;
case ButtonRelease:
//...
break;
default:
break;
}
}
return 0;
}
Does anyone has an idea about this weird problem?
Thanks a lot!

The problem is caused by using multi-threading with the 2 threads trying to access the display at the same.
strace will change the timing, so the threads are accessing the display at different times.
Xlib does have functions to prevent conflict. Lookup XInitThreads, which enables thread support and XLockDisplay and XUnlockDisplay, which you will need to call from each thread before and after accessing the display.

Related

Pthread semaphore TCP

I wanna create 2 threads in client, each thread will send a message to server and get rebounce or download a file from server, using TCP protocole. This program run very well when I didn't add pthread in it. After I created 2 threads in client, It doesn't communicate with server. Normally, thread will tell server which operation it wants, then server respond, but when one thread send the message, there is no respond from server, and this thread exit immediately, next thread occupy the semaphore but exit without chose the operation.
Code
void semaphore()
{
int nThread = 2;
int nSemaphore = 1;
int nRet = -1;
pthread_t threadIDs[nThread];
nRet = sem_init(&sem, 0, nSemaphore);
if(nRet == -1)
{
perror("Semaphore intialization failed!!!\n");
exit(EXIT_FAILURE);
}
int i;
for (i = 0; i < nThread; ++i)
{
nRet = pthread_create(&threadIDs[i], NULL, thread, NULL);
if(nRet != 0)
{
perror("pthreas_create failed!!!\n");
exit(EXIT_FAILURE);
}
}
for(i = 0; i < nThread; ++i)
{
nRet = pthread_join(threadIDs[i], NULL);
if(nRet != 0)
{
printf("Threan %d join failed!!!\n", i);
exit(EXIT_FAILURE);
}
}
sem_destroy(&sem);
}
enter code here
void *thread(void* p)
{
pthread_t id = pthread_self();
sem_wait(&sem);
pthread_mutex_lock(&mutex);
int operation ;
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口
printf("\nThis is client %ld", id);
printf("\nWhich operation do you want:\n");
printf("1:Sending message to server and get rebound\n");
printf("2:Downlown a file from server\n");
scanf("Your chose:%d", &operation);
switch(operation)
{
case 1:
{
sendMessage(serv_addr);
break;
}
case 2:
{
download(serv_addr);
break;
}
default:
break;
}
sem_post(&sem);
pthread_mutex_unlock(&mutex);
}
From terminal
This is client 139671599236864
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Your choise:1
This is client 139671590844160
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Can someone tell me where is the problem?

How does my C application communicate with bluetoothctl?

In C language, I want to develop an application to run bluetoothctl, and then send command to it and receive the info, like we run bluetoothctl in console.
int main(void)
{
int fd, err = 0;
char* tty;
wait_pid = -1;
printf("BLEapp program start.......\r\n");
if (wait_pid == -1) {
printf("Start to run bluetoothctl......\r\n");
if ((pid = fork()) < 0) {
err = 1;
printf("Create new progress failed.\r\n");
}
else if (pid == 0) {
// Child progress, run as default when xid = 0x0 and mastAddr = 0x0
execl("/root/bluez-5.42/client/bluetoothctl", "bluetoothctl", NULL);
}
}
else {
printf("The child procress is still running.....\r\n");
err = 1;
}
//tty = ttyname(STDIN_FILENO);
//printf("stdin name is %s.\r\n", tty);
//fd = open(tty, O_WRONLY);
//if (fd < 0) {
// printf("Open stdin error..............\r\n");
//}
while (1) {
sleep(2);
fputs("devices\n", stdin);
//write(fd, "devices\n", 8);
}
return err;
}
I run bluetoothctl as child process, and want to send "devices\n" command to it, and read the listed devices. But it doesn't work.
Please help me to fix this problem.
Thanks.

Understanding the use of memset in this example

I'm studying an example from the Linux Device Driver book(http://lwn.net/Kernel/LDD3/), and I don't understand the use and usefullness of the function memset in this context and I hoped that someone could explain it to me. I understand that we allocate memory for our device structure using kmalloc and with memset we put 0's in front of the memory address? Here is the example nonortheless:
int scull_p_init(dev_t firstdev)
{
int i, result;
result = register_chrdev_region(firstdev, scull_p_nr_devs, "scullp");
if (result < 0) {
printk(KERN_NOTICE "Unable to get scullp region, error %d\n", result);
return 0;
}
scull_p_devno = firstdev;
scull_p_devices = kmalloc(scull_p_nr_devs * sizeof(struct scull_pipe), GFP_KERNEL);
if (scull_p_devices == NULL) {
unregister_chrdev_region(firstdev, scull_p_nr_devs);
return 0;
}
memset(scull_p_devices, 0, scull_p_nr_devs * sizeof(struct scull_pipe));
for (i = 0; i < scull_p_nr_devs; i++) {
init_waitqueue_head(&(scull_p_devices[i].inq));
init_waitqueue_head(&(scull_p_devices[i].outq));
init_MUTEX(&scull_p_devices[i].sem);
scull_p_setup_cdev(scull_p_devices + i, i);
}
The memset is not putting 0 in front of scull_p_devices. It is overwriting the memory from the address in scull_p_devices up to the size of the allocated region with zeros.

madvise() function not working

I am trying madvise() to mark allocated memory as mergeable so that two applications having same pages can be merged.
While using the madvise() function it shows "invalid argument".
#include<stdio.h>
#include<sys/mman.h>
#include<stdlib.h>
#include<errno.h>
#define ADDR 0xf900f000
int main()
{
int *var1=NULL,*var2=NULL;
size_t size=0;
size = 1000*sizeof(int);
var1 = (int*)malloc(size);
var2 = (int *)malloc(size);
int i=0;
for(i=0;i<999;i++)
{
var1[i] = 1;
}
for(i=0;i<999;i++)
{
var2[i] = 1;
}
i = -1;
while(i<0)
{
i = madvise((void *)var1, size, MADV_MERGEABLE); //to declare mergeable
printf("%d %p\n", i, var1); //to print the output value
err(1,NULL); //to print the generated error
i = madvise((void *)var2, size, MADV_MERGEABLE); //to declare mergeable
printf("%d\n", i);
}
return 0;
}
Error:
a.out: Invalid argument
Please help me.
Thank You.
You can only merge whole pages. You can't merge arbitrary chunks of data.

Problem with wsarecv while using with IOCP

I am new to IOCP and struggling with this for last few weeks.
I have pasted some core part of my code below related to IOCP.This may not be executed perfectly as I clipped some part to make it easy to understand.
I am struggling while receiving the data.As it comes to wsarecv in worket thread, wsarecv returns WSA_IO_PENDING error code so I call WSAGetOverlappedResult to check operation to be completed.
Twist comes here, rather it proceed and call my local function ProcessTelegramData after WSAGetOverlappedResult , same part of code(wsarecv called again) is executed again by another worker thread which try to call ProcessTelegramData and buffer value is invalid in it.
I am unable to understand
why another thread calling wsarecv again when WSAGetOverlappedResult is called and
why buffer value is getting invalidated?
unsigned LicTCPServer::WorkerThread(LPVOID lpParam)
{
//int nThreadNo = (int)lpParam;
LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam);
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
//Worker thread will be around to process requests, until a Shutdown event is not Signaled.
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&lpContext,
&pOverlapped,
INFINITE);
if (NULL == lpContext)
{
//We are shutting down
break;
}
//Get the client context
pClientContext = (CClientContext *)lpContext;
if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/)
{
//Client connection gone, remove it.
pThis->RemoveFromClientListAndFreeMemory(pClientContext);
continue;
}
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
//printf("reached %d\n",pClientContext->GetOpCode());
printf("Get Queued received\n");
switch (pClientContext->GetOpCode())
{
case OP_READ:
{
//Once the data is successfully received, we will print it.
//pClientContext->SetOpCode(OP_WRITE);
pClientContext->ResetWSABUF();
dwFlags = 0;
//int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0);
//Get the data.
if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("Error occured at WSARecv()\n");
return 0;
}
}
DWORD byteTr = 0;
WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags);
if( byteTr > 0 )
{
//doing some operatin on data received
printf("Process tele called\n");
g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr);
}
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
//Send the message back to the client.
pClientContext->SetOpCode(OP_READ);
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
//p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
DWORD temp;
//Overlapped send
printf("reached Going to send\n");
//send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0);
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
&temp, dwFlags, p_ol, NULL);
if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
break;
default:
printf("reached to default\n");
//We should never be reaching here, under normal circumstances.
break;
} // switch
} // while
return 0;
}
I had a similar issue with WSARecv where it always queued to the io completion queue, even if it succeeded immediately. I had to ignore a return value indicating success and instead handle the queued result that I got from GetQueuedCompletionStatus.

Resources