Mutex do not work with two processes running - c

I'm programming in C using win32 api.
My program starts at void main , I do some action that create mutex with specific name
and then launching waitForSingleObject function on it with INFINITE time parameter.
Then I'm launching an EXE process by createProcess function.
The EXE process has a similar code that is now doing createMutex with the same name I did before with the parent process.
As I understand I should get a handle to the same mutex I created in the parent program.. because it has the same name.
So after that, the EXE code is also doing again WaitForSingleObject on the mutex handle
with same parameters.
I have expected this to stop and wait now but it continued as it was signaled somehow, but there is no way I did a signal anywhere at this stage.
I tried to replace the INFINITE parameter with 0 and to see if I get WAIT_TIMEOUT but this didn't work also.
Why my mutex don't work?
Thanks
relevant code added: (I tried to put only things that are relevant)
* please note the the EXE file Process1 contains a code that does openfileInDirectory with the same file name I did in void main and for write.
** My mutex to follow is that is called writeMutex. FileSystemMutex is another one that has nothing to do with my current problem.
// Global variables definition from library header
void* viewVec;
HANDLE fileHandle;
int directoryLastBlockIndex;
FilesInProcessUse processFiles;
HANDLE fileSystemMutex;
HANDLE filesAccessSemaphore;
void main()
{
FileDescriptor* fd, *fd2;
int message,message2,message3;
int processId = GetCurrentProcessId();
char* input= NULL;
/* print out our process ID */
printf("Process %d reporting for duty\n",processId);
fileSystemMutex = CreateMutex(NULL,FALSE,FILE_SYSTEM_MUTEX_NAME);
printf("Process %d: After creating fileSystem mutex\n",processId);
filesAccessSemaphore = CreateSemaphore(NULL,MAX_ACCESSORS_FOR_ALL_FILES,MAX_ACCESSORS_FOR_ALL_FILES,FILE_SYSTEM_SEMAPHORE_NAME);
printf("Process %d: After creating filesAccessSemaphore\n",processId);
initfs("C",NUM_OF_BLOCKS_IN_DISK,NUM_OF_BLOCKS_IN_DISK);
viewVec = attachfs("C"); // Saving the address of the vector in global pointer.
if(viewVec!=NULL)
{
printf("Process %d: After AttachFS which succeded\n",processId);
fd = (FileDescriptor*) createFileInDirectory("FileX",2,&message);
if (fd!=NULL)
{
printf("Process %d:successfuly created the file: FileX in Drive C\n",processId);
}
else
{
printErrMessage(message);
}
}
else
{
printf("Process %d: After AttachFS, which failed\n",processId);
}
fd = (FileDescriptor*) openFileInDirectory("FileX",READ_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileXfile for read succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
closeFileInDirectory(fd);
fd = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileXfile for write succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
fd2 = (FileDescriptor*) openFileInDirectory("FileX",WRITE_PERMISSION,&message);
if(fd!=NULL)
{
printf("Process %d: opened FileX file for write succefully",processId);
}
else
{
printf("Process %d:",processId);
printErrMessage(message);
}
}
}
void* openFileInDirectory(char* fileName, int ReadWriteFlag, int* out_ErrMessage)
{
SystemInfoSection* sysInfo = readSystemInformationFromBeginingOfVector((char*)viewVec);
DirectoryEntry* fileEntryInDirOffset;
FileDescriptor* openfileDescriptor = NULL;
int fileIndexInOpenFiles = 0;
int writeRV;
//Mark that another file is being processed
WaitForSingleObject(filesAccessSemaphore,INFINITE);
//Check if the file exists else return error
if(isFileAlreadyExisting(fileName, sysInfo->directoryStartBlockIndex, &fileEntryInDirOffset))
{
fileIndexInOpenFiles = getFileIndexInOpenFileDirectory(fileName);
processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore = CreateSemaphore(NULL,MAX_FILE_ACCESSORS,MAX_FILE_ACCESSORS,fileName);
WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,INFINITE);
if (ReadWriteFlag == WRITE_PERMISSION)
{
char writeMutexName[15];
strcpy(writeMutexName, WRITE_MUTEX_PREFIX);
strcat(writeMutexName, fileName);
processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex = CreateMutex(NULL,FALSE,writeMutexName);
WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,INFINITE);
//writeRV = WaitForSingleObject(processFiles.allFilesVector[fileIndexInOpenFiles].writeMutex,MAX_WAIT_TIMEOUT_IN_FS);
//if(writeRV == WAIT_TIMEOUT)
//{
// ReleaseSemaphore(processFiles.allFilesVector[fileIndexInOpenFiles].accessSemaphore,1,NULL);
// //return error indicating that another process is already writing to the file AND RETURN FROM THE FUNCTION
// *out_ErrMessage = ERR_FILE_IS_ALREADY_OPEN_TO_A_WRITE_BY_SOME_PROCESS;
// return openfileDescriptor;
//}
}
processFiles.FDInProcessUseVector[fileIndexInOpenFiles].fileDirectoryEntry = fileEntryInDirOffset;
processFiles.FDInProcessUseVector[fileIndexInOpenFiles].readWriteFlag = ReadWriteFlag;
openfileDescriptor = &(processFiles.FDInProcessUseVector[fileIndexInOpenFiles]);
processFiles.numOfFilesInUse++;
}
else
{
openfileDescriptor = NULL;
*out_ErrMessage = ERR_FILE_NOT_FOUND;
}
free(sysInfo);
return openfileDescriptor;
}

You can use CreateMutex function to create named global mutex.
Logic of using global mutex is usually following:
You try to create mutex by using CreateMutex. Note that "If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object".
You lock (get ownership) by using WaitForSingleObject function
You unlock (release ownership) by using ReleaseMutex function
You CloseHandle returned by CreateMutex function.
Here is good example in C: Using Mutex Objects
There are few problems in your code:
You don't release ownership of writeMutex, which is probably the main reason why this code can't work.
You don't check the return value of a single call. The only return value that you check is the one returned from your function. Check documentation of these functions so that you can handle possible error states properly.
You don't CloseHandle returned by CreateMutex function. Neither handle of fileSystemMutex nor handle of writeMutex.
You create fileSystemMutex, but then you never use it. This mutex has no sense there.

Related

C How to share informations between processes?

I would need some help with some C code.
Basically I have n processes which execute some code. Once they're almost done, I'd like the "Manager Process" (which is the main function) to send to each of the n processes an int variable, which may be different for every process.
My idea was to signal(handler_function, SIGALRM) once all processes started. When process is almost done, it uses kill(getpid(), SIGSTOP) in order to wait for the Manager Process.
After SIM_TIME seconds passed, handler_function sends int variable on a Message Queue then uses kill(process_pid, SIGCONT) in order to wake up waiting processes. Those processes, after being woken up should receive that int variable from Message Queue, print it and simply terminate, letting Manager Process take control again.
Here's some code:
/**
* Child Process creation using fork() system call
* Parent Process allocates and initializes necessary variables in shared memory
* Child Process executes Student Process code defined in childProcess function
*/
pid_t runChild(int index, int (*func)(int index))
{
pid_t pid;
pid = fork();
if (pid == -1)
{
printf(RED "Fork ERROR!\n" RESET);
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
int res = func(index);
return getpid();
}
else
{
/*INSIGNIFICANT CODE*/
currentStudent = createStudent(pid);
currentStudent->status = FREE;
students[index] = *currentStudent;
currentGroup = createGroup(index);
addMember(currentStudent, currentGroup);
currentGroup->closed = FALSE;
groups[index] = *currentGroup;
return pid;
}
}
Code executed by each Process
/**
* Student Process Code
* Each Student executes this code
*/
int childProcess(int index)
{
/*NOTICE: showing only relevant part of code*/
printf("Process Index %d has almost done, waiting for manager!\n", index);
/* PROGRAM GETS STUCK HERE!*/
kill(getpid(), SIGSTOP);
/* mex variable is already defines, it's a struct implementing Message Queue message struct*/
receiveMessage(mexId, mex, getpid());
printf(GREEN "Student %d has received variable %d\n" RESET, getpid(), mex->variable);
}
Handler Function:
* Handler function
* Will be launched when SIM_TIME is reached
*/
void end_handler(int sig)
{
if (sig == SIGALRM)
{
usleep(150000);
printf(RED "Time's UP!\n" RESET);
printGroups();
for(int i = 0; i < POP_SIZE; i++){
mex->mtype = childPids[i];
mex->variable = generateInt(18, 30);
sendMessage(mexId, mex);
//childPids is an array containing PIDs of all previously launched processes
kill(childPids[i], SIGCONT);
}
}
I hope my code is understandable.
I have an issue though, Using provided code the entire program gets stuck at kill(getpid(), SIGSTOP) system call.
I also tried to launch ps in terminal and no active processes are detected.
I think handler_function doesn't send kill(childPids[i], SIGCONT) system call for some reason.
Any idea how to solve this problem?
Thank you
You might want to start by reading the manual page for mq_overview (man mq_overview). It provides a portable and flexible communication mechanism between processes which permits sync and async mechanisms to communicate.
In your approach, there is a general problem of “how does one process know if another is waiting”. If the process hasn’t stopped itself, the SIGCONT is ignored, and when it subsequently suspends itself, nobody will continue it.
In contrast, message-based communication between the two can be viewed as a little language. For simple exchanges (such as yours), the completeness of the grammar can be readily hand checked. For more complex ones, state machines or even nested state machines can be constructed to analyze their behaviour.

What happens after the execution of a handler function on the SIGCHLD signal in C?

I was wondering what exactly happens after the execution of a handler on a signal in C, more specifically on the SIGCHLD signal.
I'm actually building a shell and I need to do this:
User enters a command with "&" as the last argument
A new process is created with fork
The parent process returns to the main function and wait for a new input from the user
The child process executes in the background
The child process ends and SIGCHLD is triggered
The parent process handles the death of his child
My code do all of these points, but behaves in a strange way at the very end when the handler function returns.
My implementation
Main loop
int
main()
{
// SIGNALS HANDLING :
sigaction(SIGTERM, NULL, NULL);
sigaction(SIGQUIT, NULL, NULL);
// Current location
char* path = malloc(PATHMAX);
int argc;
char** argv;
// main loop
while(1)
{
getcwd(path, PATHMAX);
printf("%s$ ",path);
argc = 0;
// Parsing
argv = malloc(MAX_INPUT); // user's input is limited to 100000 characters
getParameters(argv, &argc);
// First we check if the user wants to execute the task in background
if ( strcmp(argv[argc-1],"&") == 0 ) {
// builtin functions can't be executed in background:
int isExit = (strcmp(argv[0],"exit") == 0) ? 1 : 0;
int isCd = (strcmp(argv[0],"cd") == 0) ? 1 : 0;
if(isExit || isCd) {
printf("Built-in functions can't be executed in background. \n");
} else {
// Execute the job in background
// First we delete the last arg
argv[argc-1] = NULL;
argc--;
execBackground(argv,argc);
}
} else {
// Execute built-in functions
if(!(exeBuiltin(argv, argc))) {
// Execute jobs if no builtin functions were executed
exeJob(argv,argc);
}
}
free(argv);
}
return 0;
}
User's input processing
// max 100000 characters
char input[MAX_INPUT];
// read keyboard inputs
fgets(input,MAX_INPUT,stdin);
Built-in functions (cd and exit)
int exeBuiltin(char** argv, int argc) {
// execute builtin functions if it exists
char* builtin[2];
builtin[0] = "exit";
builtin[1] = "cd";
// run through the arguments
for(int i = 0; i < argc; i++) {
// exit
if (strcmp(argv[i],builtin[0]) == 0) {
exitBuiltin(EXIT_SUCCESS);
} else if (strcmp(argv[i],builtin[1]) == 0) {
// cd
if (argc >= 2) {
cdBuiltin(argv[i+1]);
return 1;
}
}
}
return 0;
}
static void cdBuiltin(char* path) {
if(chdir(path) == -1) {
printf("%s\n",strerror(errno));
};
}
static void exitBuiltin(int signal) {
exit(signal);
}
Link between signal and handler:
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = child_handler;
sigaction(SIGCHLD, &sa, NULL);
Handler:
static void child_handler(int sig)
{
int status;
/* kills process
pid is a global variable that is set when I call fork() */
if(waitpid(pid, &status, 0) != -1) {
if (status == 0) // Verify child process terminated without error.
{
// success
printf("\nBackground job exited with code 0\n");
}
if (status == 1)
{
// error
printf("\nBackground job exited\n");
}
}
return;
}
The problem
My problem occurs when I call something like:
sudo apt-get update &
cd ../
Then when the sudo command terminates (the handler is called and prints "Background job exited with code 0"), even though the command "cd ../" is already executed it gets executed again.
The ouput looks like:
$ /home/ubuntu/workspace$ sudo apt-get update &
$ /home/ubuntu/workspace$ cd ../
$ /home/ubuntu$
Background job exited with code 0
$ /home$
Additional information:
cd is a builtin function which only does: chdir(path) with a path given, and the path is simply output with a printf("%s$",path) at the beginning of every loop in the main (after a command has been called).
The question
In order to understand what the real problem is, I believe that I should understand what happens at the end of my child_handler function.
If I'm at a certain point in the code with the main process, say waiting on the user input, and the background process dies, child_handler is called and then what? Does it change anything for the main process or is it still a the same point in the code, waiting for an input?
Thanks for you help.
One definite problem is that you are calling printf in your signal handler, and printf is not async-safe, so if the SIGCHLD happens while in any library function (such as fgets waiting to read a line of input perhaps?), you get undefined behavior. Perhaps corrupting the stdio file buffers and causing it to act as if the input was duplicated.
You need to very careful how you write the code in your signal handler, making sure it cannot call (directly or indirectly) and non-async-safe library function, and ensuring that all the code is itself async-safe with respect to any side effects in other parts of your program.
As #ChrisDodd said, the problem was that a system call (fgets), was interrupted by the death of the background process and caused undefined behaviour.
Therefore, I solved my problem by adding the following flag to my handler:
sa.sa_flags = SA_RESTART;
As the documentation says it will:
Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.
Thus no more issue with fgets.

KERNEL_APC_PENDING_DURING_EXIT BSOD

I am setting a PLOAD_IMAGE_NOTIFY_ROUTINE to detect a specific image name and if there's a match, then terminate it. I am getting a KERNEL_APC_PENDING_DURING_EXIT BSOD though. The BSOD is happening somewhere in my KillProcess function which simply just opens a kernel handle with ObOpenObjectByPointer then calls ZwTerminateProcess on that handle.
What could be wrong? The code works fine outside the routine. Do I have to post it? I am getting a BSOD in my PLOAD_IMAGE_NOTIFY_ROUTINE when I call KillProcess.
Here is my KillProcess function:
NTSTATUS KillProcess(HANDLE ProcessId)
{
PEPROCESS Process;
HANDLE newProcessHandle = NULL;
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &Process);
do
{
if (!NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Process with id %d does not exist\n", ProcessId);
#endif
break;
}
if (NT_SUCCESS(status = ObOpenObjectByPointer(
Process,
OBJ_KERNEL_HANDLE,
NULL,
PROCESS_TERMINATE,
*PsProcessType,
KernelMode,
&newProcessHandle
)))
{
if (newProcessHandle != NULL)
{
status = ZwTerminateProcess(newProcessHandle, 0);
ZwClose(newProcessHandle);
}
else
{
ObDereferenceObject(Process);
break;
}
if (NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Successfully killed process with id %d\n", ProcessId);
#endif
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to kill process with id %d\n", ProcessId);
#endif
}
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to open process with id %d\n", ProcessId);
#endif
}
ObDereferenceObject(Process);
} while (FALSE);
return status;
}
The documentation for PsSetLoadImageNotifyRoutine says:
When the main executable image for a newly created process is loaded, the load-image notify routine runs in the context of the new process.
(It also seems likely that when a DLL is loaded, the call is made in the context of the process loading the DLL.)
So from the sounds of it, you are terminating the process whose context you are running in. What's more, you're doing it at a particularly vulnerable point, during a callback for an image load operation. It is not surprising that this causes trouble.
The documentation for ZwTerminateProcess implies that a driver can terminate the current process, provided that it ensures that resources have been freed from the kernel stack, but I don't think that applies in this situation. (Also, I don't know how you'd go about doing that.)
It might instead be possible to suspend the process, and terminate it later from a system thread.
The problem is I was trying to terminate the process in its own context which lead to a BSOD.
Solution:
Create a global variable holding the pid
Set the global variable
In a system thread, check if the global variable has changed
terminate the process

C programming. Using execl and pthread

I'm having a problem in the combined use of execl() and pthread.
My idea is quite simple: write a daemon that in certain situation starts an external process (a separate executable with respect to the daemon itself) and wait for the return value of that process. Moreover I want to have the possibility to start multiple instances of the same process at the same time.
The part of my code to handle multiple threads:
...
for (c_thread=0,i=0;i<N;i++)
{
/* Start actions before start threads */
for (j=c_thread;j<c_thread+config.max_threads;j++)
Before_Process(act[act_index[j]].measID);
/* Now create threads */
for (c=0,j=c_thread;j<c_thread+config.max_threads;j++)
{
Print_Log(LOG_DEBUG,"Create tread n. %d, measurementID=%s",c,act[act_index[j]].measID);
if ((ret=pthread_create(&pth[c],NULL,Start_Process_Thread,(void *) &act[act_index[j]].measID)))
{
Print_Log(LOG_ERR,"Error in creating thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
c++;
}
/* Joint threads */
for (j=0;j<config.max_threads;j++)
{
if ((ret=pthread_join(pth[j], (void**) &r_value[j])))
{
Print_Log(LOG_ERR,"Error in joint thread (errorcode: %d)",ret);
exit(EXIT_FAILURE);
}
}
/* Perform actions after the thread */
for (j=0;j<config.max_threads;j++)
{
status=*(int*) r_value[j];
Print_Log(LOG_DEBUG,"Joint tread n. %d. Return value=%d",j,status);
After_Process(act[act_index[c_thread+j]].measID,status);
}
c_thread += config.max_threads;
}
...
And the function Start_Process_Thread:
void *Start_Process_Thread(void *arg)
{
int *ret;
char *measID;
measID=(char*)arg;
if (!(ret=malloc(sizeof(int))))
{
Print_Log(LOG_ERR, "allocation memory failed, code=%d (%s)",
errno, strerror(errno) );
exit(EXIT_FAILURE);
}
*ret=Start_Process(measID);
pthread_exit(ret);
}
int Start_Process(char *measID)
{
...
pipe(pfd);
pid=fork();
if (!pid)
{
signal(SIGALRM,Timeout);
alarm(config.timeout_process);
flag=0;
/*
Start the Process.
*/
ret=execl(config.pre_processor,buff_list[TokCount-1],config.db_name,measID,(char *) 0);
if (ret==-1)
{
alarm(0);
flag=1;
Print_Log(LOG_ERR,"Cannot run script %s, code=%d (%s)",config.process, errno, strerror(errno));
}
alarm(0);
close(1);
close(pfd[0]);
dup2(pfd[1],1);
write(1,&flag,sizeof(int));
}
else
{
wait(&status);
close(pfd[1]);
read(pfd[0],&flag,sizeof(int));
close(pfd[0]);
if (!flag)
{
if (WIFEXITED(status))
{
if (!(return_value=WEXITSTATUS(status)))
{
/*
Process gives no errors.
*/
Print_Log(LOG_INFO, "Processing of measurementID=%s ended succesfully!",measID);
}
else
{
/*
Process gives errors.
*/
Print_Log(LOG_WARNING,"Processor failed for measurementID=%s, code=%d",measID, return_value);
}
}
else
{
/*
Timeout for Process
*/
Print_Log( LOG_WARNING,"Timeout occurred in processing measurementID=%s",measID);
return_value=255;
}
}
}
}
The above code works fine from technical point of view but I have a problem somewhere in handling the return values of the different instances of the called external process. In particular it happens that the return value associated to a certain instance is attributed to a different one randomly.
For example suppose 4 different instances of the external process are called with the arguments meas1, meas2, meas3 and meas4 respectively and suppose that meas1, meas2 and meas3 are successfully processed and that for meas4 the process fails. In situation like that my code mix up the return vales giving success for meas1, meas3, and meas4 and failure for meas2 or success for meas1, meas2, meas4 and failure for meas3.
Any idea on why this can happens?
Any help is really welcome.
Thank you in advance for your attention.
When any thread in a process executes wait(), it gets the information about any of the process's dead children — not necessarily about the last child started by the thread that is doing the waiting.
You are going to need to think about:
Capturing the PID of the process that died (it is returned by wait(), but you ignore that).
Having a single thread designated as the 'disposer of corpses' (a thread that does nothing but wait() and record and report on deaths in the family of child processes).
A data structure that allows the threads that start processes to record that they are interested in the status of the child when it dies. Presumably, the child should wait on a suitable condition once a child starts so that it is not consuming CPU time doing nothing useful.
The 'disposer of corpses' thread handles notifications of the appropriate other thread whenever it collects a corpse.
Worry about timeouts on the processes, and killing children who run wild for too long.
It's a morbid business at times...

Using a global variable to control a while loop in a separate thread

gcc (GCC) 4.6.3
c89
valgrind-3.6.1
Hello,
Updated code snippet
+++++++++++++++++++++++++++++++++++
void *thread_recv_fd()
{
pthread_mutex_lock(&mutex_queue);
while(start_receiving) {
pthread_mutex_unlock(&mutex_queue);
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
using the above locks looks very ugly now. And I am still getting a race error on the reading of the start_receiving. I have also declared it as volatile as well.
+++++++++++++++++++++++++++++++++++++
I am running a while loop in a worker thread that polls every 1/2 second. I control it with a global variable start_receiving after the user enters ctrl-c it will change the value to false.
Having a global like this is it good practice?
The reason I asked as I get these 2 errors when I run helgrind:
==6814== Possible data race during write of size 4 at 0x601958 by thread #1
==6814== at 0x401131: main (driver.c:78)
==6814== This conflicts with a previous read of size 4 by thread #2
==6814== at 0x4012A7: thread_recv_fd (driver.c:127)
This are the lines of code:
driver.c:78 is this line of code start_receiving = FALSE;
driver.c:127 is this line of code while(start_receiving) in the while loop
Source code, just the important snippets:
static int start_receiving = FALSE;
int main(void)
{
pthread_t thread_recv_id;
pthread_attr_t thread_attr;
/* Start polling as soon as thread has been created */
start_receiving = TRUE;
do {
/* Start thread that will send a message */
if(pthread_create(&thread_recv_id, &thread_attr, thread_recv_fd, NULL) == -1) {
fprintf(stderr, "Failed to create thread, reason [ %s ]",
strerror(errno));
break;
}
}
while(0);
/* Wait for ctrl-c */
pause();
/* Stop polling - exit while loop */
start_receiving = FALSE;
/* Clean up threading properties */
pthread_join(thread_recv_id, NULL);
pthread_exit(NULL);
}
void *thread_recv_fd()
{
while(start_receiving) {
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
Many thanks for any suggestions,
No, it's very bad practice.
At the very least, the variable should be volatile to avoid being optimized out.
You should really look into using some real multi-thread primitives for this though, such as mutexes (to protect the shared state, so that the two threads aren't accessing it at the same time) and atomic variables (to make sure the state is thread-proof).
Polling isn't a right way.
I suggest you to read about conditional variables
You could use atomics, but the simplest solution here is just to use locking around the controlling variable. For example:
static int start_receiving = FALSE;
static pthread_mutex_t start_receiving_lock = PTHREAD_MUTEX_INITIALIZER;
int is_receiving(void)
{
int r;
pthread_mutex_lock(&start_receiving_lock);
r = start_receiving;
pthread_mutex_unlock(&start_receiving_lock);
return r;
}
Then in the thread function:
void *thread_recv_fd()
{
while(is_receiving()) {
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
..and in the main function:
pthread_mutex_lock(&start_receiving_lock);
start_receiving = 1;
pthread_mutex_unlock(&start_receiving_lock);

Resources