using flock, open and close file to implement many readers single writer lock - c

I've got a project that consist of multiple processes that can read or write into a single data base. I wish to implement single writer / multi readers locks synchronized by a lock file using the system calls flock/open/close.
Upon lock failure, any re-attempt to take the lock again, will be made by the higher level that requested the lock (unlike spin-lock).
Unfortunately, while testing this model, it failed on scenario of unlocking that wasn't preceded by locking.
perhaps you can help me find what did i do wrong here:
// keep read and write file descriptors as global variables.
// assuming no more than 1 thread can access db on each process.
int write_descriptor=0;
int read_descriptor=0;
int lock_write() {
if((write_descriptor = open(LOCKFILE, O_RDWR|O_CREAT,0644))<0) {
return LOCK_FAIL;
}
if(flock(write_descriptor, LOCK_EX)<0) {
close(write_descriptor);
write_descriptor = 0;
return LOCK_FAIL;
}
return LOCK_SUCCESS;
}
int unlock_write() {
if(!write_descriptor) {
// sanity: try to unlock before lock.
return LOCK_FAIL;
}
if(flock(write_descriptor,LOCK_UN)<0) {
// doing nothing because even if unlock failed, we
// will close the fd anyway to release all locks.
}
close(write_descriptor);
write_descriptor = 0;
return LOCK_SUCCESS;
}
int lock_read() {
if((read_descriptor = open(LOCKFILE,O_RDONLY))<0) {
return LOCK_FAIL;
}
if(flock(read_descriptor, LOCK_SH)<0) {
close(read_descriptor);
return LOCK_FAIL;
}
return LOCK_SUCCESS;
}
int unlock_read() {
if(!read_descriptor) {
// sanity : try to unlock before locking first.
return LOCK_FAIL;
}
if(flock(read_descriptor, LOCK_UN)<0) {
// doing nothing because even if unlock failed, we
// will close the fd anyway to release all locks.
}
close(read_descriptor);
read_descriptor = 0;
return LOCK_SUCCESS;
}
int read_db() {
if(lock_read() != LOCK_SUCCESS) {
return DB_FAIL;
}
// read from db
if(unlock_read() != LOCK_SUCCESS) {
// close fd also unlock - so we can fail here (can i assume that ?)
}
}
int write_db() {
if(lock_write() != LOCK_SUCCESS) {
return DB_FAIL;
}
//write to db.
if(unlock_write() != LOCK_SUCCESS) {
// close fd also unlock - so we can fail here (can i assume that ?)
}
}

In both lock_read and lock_write add this as the first line:
assert ((read_descriptor == 0) && (write_descriptor == 0));
In unlock_read, add this:
assert (read_descriptor != 0);
And in unlock_write, add this:
assert (write_descriptor != 0);
And change code like:
if(flock(read_descriptor, LOCK_SH)<0) {
close(read_descriptor);
return LOCK_FAIL;
}
to:
if(flock(read_descriptor, LOCK_SH)<0) {
close(read_descriptor);
read_descriptor = 0;
return LOCK_FAIL;
}
Do the same for the write code so that any time a descriptor is closed, the corresponding global is set to zero. (You really should use -1 for an invalid file descriptor since zero is legal.)
Make a debug build and run it. When an assert trips, you'll have your culprit.

Related

Getting result of exec*() from child process without waiting in any case (not using pipes and vfork())

I am working on custom wrappers for Unix-specific system calls now. And the last problem I met is about how to create a complete function for creating new processes with another image. And I want this function to return TRUE or FALSE. The last piece of this puzzle is how to get a result of exec*() from a child process without waiting for it's end in case of exec*()'s success. In other words, I need to get FAIL of SUCCESS result of exec*() quickly and continue execution of a parent process.
And I don't want to use vfork() and pipes.
My current results:
Using vfork() and a volatile variable for keeping result made their work.
static int QCreateProcess(char* args, ...)
{
if (processInfoStruct == NULL)
{
return Q_ERROR;
}
volatile int result = TRUE;
pid_t procHandle = vfork();
if (procHandle == 0)
{
char* argsToExec[2] = { args, NULL };
execv(argsToExec[0], argsToExec);
result = FALSE;
_exit(EXIT_FAILURE);
}
else if (procHandle == -1)
{
processInfoStruct->processHandle = NULL;
result = FALSE;
}
else
{
if (result == TRUE)
{
waitpid(procHandle, NULL, WNOHANG);
processInfoStruct->processHandle = procHandle;
}
else
{
processInfoStruct->processHandle = 0;
result = FALSE;
}
}
return result;
}
This code works and returns correct results.
How can this be implemented using fork() and waitpid() without the status variable (it won't work with fork() anyway...) and pipes? I tried to find solutions with different options for the last function (waitpid()), but a desired combination was not found.

accept call blocking thread termination

I'm having trouble terminating my server in my multithreaded program (one server, multiple clients).
When the variable global_var, which counts the number of currently connected clients, gets set to 0, the server should terminate, but it doesn't.
What I think is happening is since accept() is blocking , the code never reaches the break condition in main loop.
It's breaking correctly out of thread_func but then it blocks inside the while loop, just before the accept() call and after printing "Exiting thread_func".
volatile int finished = 0; // Gets set to 1 by catching SIGINT/SIGSTOP
int global_var = 0; // When it gets to 0, server should terminate
int server_fd;
void * thread_func(void* arg)
{
do_some_pre_stuff();
while(1)
{
if(!global_var)
{
close(server_fd);
finished = 1;
break;
}
if(recv(...) > 0)
{
do_more_stuff()
}
else
{
disconnect_client();
global_var--;
break;
}
}
free_more_ressources();
return NULL;
}
int main()
{
do_initial_stuff();
init_socket();
listen();
while (!finished)
{
if( (fd = accept(server_fd,...)) == -1)
exit(-1);
global_var++;
/* Some intermediate code */
if(!global_var)
break;
// Thread for the newly connected player
if(pthread_create(&thread_id[...], NULL, thread_func, (void*)some_arg)
exit(-1);
}
free_resources();
puts("Exiting thread_func");
}
I tried the advice listed here without success (except the pipe answer, not trying to mess with pipes).
I'm new to socket programming but what I tried so far looked correct but none of the solutions worked (including semaphores, pthread_cancel,etc)
PS: synchronization has been implemented, just omitted here for readability

Closing Libuv Loop Correctly During Initialization

I am initializing a loop in libuv, but if I need to return after I initialized the loop but before I have called uv_run, how do I correctly clean up all memory and file descriptors? Here is my example code, loop being uv_loop_t* and server being uv_tcp_t*:
if (uv_loop_init(loop) < 0) {
return -1;
}
if (uv_tcp_init(loop, server) < 0) {
// What code here?
return -1;
}
if (some_other_function() < 0) {
// What code here?
return -1;
}
uv_run(loop, UV_RUN_DEFAULT);
According to this question, I should stop, walk and run the loop, closing all the handles; but that assumes I'm already running the loop, which I'm not. I could just call uv_loop_close(loop), but that doesn't free the handles.
As mentioned in the link, you need to do something like this;
uv_loop_init(&loop);
uv_tcp_init(&loop, &server);
uv_walk(&loop,
[](uv_handle_t* handle, void* arg) {
printf("closing...%p\n", handle);
uv_close(handle, [](uv_handle_t* handle) {
printf("closed...%p\n", handle);
}
);
uv_run(&loop, UV_RUN_ONCE);
},
NULL);

How to implement a "Quit Y,N" on close button pressed

I'm trying to understand windows threading system, but I recently got a problem, which I cannot fully comprehend:
I want my console not to close on close button pressed, but rather ask you if it should close or not. Now all the thing run in Thread() function, which just checks if global static volatile bool bActive == false if it is thread just ends. But I'd expect it to write some message and if it is no - continues work normally.
I've tried this:
// in console creation function
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CloseHandler, TRUE);
and
static bool CloseHandler(DWORD event)
{
if (event == CTRL_CLOSE_EVENT)
{
printf("close event");
if(bActive)
{
InterlockedDecrement(&bActive);
WaitForSingleObject(hThread, INFINITE); // just wait for thread to finish or restart
}
}
return true;
}
but it closes the app regardless of choice it has to offer.
here is the rest of the code:
DWORD _stdcall VGameThread(void* _self)
{
while (bActive)
{
while (bActive)
{
// do its things
}
if (on())
break;
else
InterlockedIncrement(&bActive);
}
}
on()
{
int i;
scanf("%d", &i);
if (i == 1)
return 1;
else
return 0;
}

What would the source code of a try lock be?

So I think I understand the source code for a signal and a wait (the wait being a lock) but I am not sure how to implement a try lock.
Here is my code for a wait:
//if s->type is zero it is a binary semaphore type
if (s->type == 0)
{
// binary semaphore
// if state is zero, then block task
if (s->state == 0)
{
// block task
// ?? move task from ready queue to blocked queue
//reschedule the tasks
return 1;
}
// state is non-zero (semaphore already signaled)
s->state = 0; // reset state, and don't block
return 0;
}
else
{
// counting semaphore
s->state--;
// ?? implement counting semaphore
if (s->state < 0)
{
}
}
This is what I have for a try lock so far:
if (s->type == 0)
{
// binary semaphore
// if state is zero, then block task
if (s->state == 0)
{
tcb[curTask].event = s; // block task
tcb[curTask].state = S_BLOCKED;
removeNode(tcb[curTask].priority, READY_QUEUE, curTask);
enqueue(tcb[curTask].priority, curTask, BLOCKED_QUEUE);
return 1;
}
// state is non-zero (semaphore already signaled)
s->state = 1; // reset state, and don't block
return 0;
}
else
{
s->state--;
if (s->state >= 0)
{
s->state++;
}
else
{
tcb[curTask].event = s;
tcb[curTask].state = S_BLOCKED;
removeNode(tcb[curTask].priority, READY_QUEUE, curTask);
enqueue(tcb[curTask].priority, curTask, BLOCKED_QUEUE);
}
}
A regular spin lock is implemented something like this (pseudo-C-codish):
void lock(locktype_t* LockVariable)
{
while (CompareAndSwap(LockVariable,
STATE_UNLOCKED /* state to wait for */,
STATE_LOCKED /* new state to try to set */) !=
STATE_UNLOCKED /* expected state at the beginning of CAS() */)
{
// spin here, doing nothing useful, waiting for *LockVariable to
// first become STATE_UNLOCKED (CAS() returns its last value), after
// which we will set it to STATE_LOCKED (CAS() will do that atomically)
}
}
void unlock(locktype_t* LockVariable)
{
*LockVariable = STATE_UNLOCKED;
}
In case where indefinite spinning and waiting for the lock to become first unlocked is undesirable, we use a loop-less variant of the above something like this:
int tryToLock(locktype_t* LockVariable)
{
if (CompareAndSwap(LockVariable,
STATE_UNLOCKED /* state to wait for */,
STATE_LOCKED /* new state to try to set */) !=
STATE_UNLOCKED /* expected state at the beginning of CAS() */)
{
return 0; // the lock is still held by someone else, bail out
}
return 1; // the lock is now held by us, hurray!
}
Compare-and-swap
I was looking for a non-spin lock trylock.
I have figured out what to do. If it is a counting semaphore, then I decrement if the count is positive and I consume the resource. If it is zero or less, I do nothing but return an error code. I do not decrement the count or consume the resource. The program is then able to continue past that point. If it is a binary semaphore, I consume it if the resource is available. I then change the value of the binary semaphore to consumed. If it isn't available, then I return an error code.

Resources