Shared Memory and semaphores for (multiple) client and server game - c

I have to program a little game for a course in C and it has to be done with using shared-memory, semaphores and a client/server architecture which can handle multiple clients (the exact requirement for the game is 2).
The two clients need to do their turns in turns and they are represented by the very same program (no fork() involved here - both started with ./client)
The server has to create all the resources when it starts up. So my main problem is regarding the semaphores. (The shared memory and the game-logic stuff works or isn't really difficult to implement.)
To decide if the server or a client has access to the shared-memory I need one semaphore. I need a second one to decide which of the clients has access. Am I right?
So I got a hint that it could be done with assigning IDs to the clients. So the shared-memory has three additional variables like so:
struct game
{
int id_needed, client_id, id_ready;
... // additional stuff that is needed for the game logic itself
};
As the server boots up I'm initializing one semaphore to be 0 and the other one to be 1.
When the first client appears it checks if his ID is still 0 (it's initialized as zero)
If so, it tries this:
while(my_id == 0)
{
if(semaphore_down(semaphore_1) == 0) // Check if I have access to shared mem
{
shared_memory->id_needed = 1;
if(shared_memory->id_ready == 1)
{
my_id = shared_memory->client_id;
(void) printf("DEBUGGING: My ID is %d\n", my_id);
}
}
}
shared_memory->id_needed = 0;
And in the server I do ...
while(1)
{
if(shared_memory->id_needed = 1)
{
(void) printf("DEBUGGING: ID is needed for another client!");
shared_memory->client_id++;
shared_memory->id_ready = 1;
(void) printf("DEBBUGING: Dispatched new ID: %d", shared_memory->client_id);
}
// If enough players, start the game ...
}
I'm really stuck here. The server just increments the ID (which is only logical), but I'm stuck as to resolve this problem.
I just want the clients to work alternately on the shared-memory and the server to check the values of the game etc.
I've never worked with semaphores before and all the documentation or examples I find do just work with one client and one server, but never multiple clients.
Please enlighten me!

I see one strange thing and two things that obviously are mistakes here
I see semaphore_down but no semaphore_up in the code you showed
you assign instead of comparing: if(shared_memory->id_needed = 1)
even if it was a comparison, it was not right anyway since compiler was free to optimize it out. Make this variable volatile to hint compiler that variable can change outside of the serial code flow. Or better declare it atomic.

Related

How to detect unreleased lock in multi-task C project using static analysis tools?

Is there any way, using static analysis tools(I'm using Codesonar now), to detect unreleased lock problems (something like unreleased semaphores) in the following program?(The comment part marked by arrows)
The project is a multi-task system using Round-robin scheduling, where new_request() is an interrupt task comes randomly and send_buffer() is another period task.
In real case, get_buffer() and send_buffer() are various types of wrappers, which contains many call layers until actual lock/unlock process. So I can't simply specify get_buffer() as lock function in settings of static analysis tool.
int bufferSize = 0; // say max size is 5
// random task
void new_request()
{
int bufferNo = get_buffer(); // wrapper
if (bufferNo == -1)
{
return; // buffer is full
}
if (check_something() == OK)
{
add_to_sendlist(bufferNo); // for asynchronous process of send_buffer()
}
else // bad request
{
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// There should be clear_buffer placed here
// but forgotten. Eventually the buffer will be
// full and won't be cleared since 5th bad request comes.
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
do_nothing();
// clear_buffer(bufferNo);
}
}
int get_buffer()
{
if(bufferSize < 5)
{
bufferSize++;
return bufferSize;
}
else
{
wait_until_empty(); // wait until someone is sent by send_buffer()
return -1;
}
}
// clear specifiled one in buffer
void clear_buffer(int bufferNo)
{
delete(bufferNo)
bufferSize--;
}
// period task
void send_buffer()
{
int sent = send_1st_stuff_in_list();
clear_buffer(sent);
}
yoyozi - Fair disclosure: I'm an engineer at GrammaTech who works on CodeSonar.
First some general things. The relevant parts of the manual for this are on the page: codesonar/doc/html/C_Module/LibraryModels/ConcurrencyModelsLocks.html. Especially the bottom of the page on Resolving Lock Operation Identification Problems.
Based on your comments, I think you have already read this, since you address setting the names in the configuration settings.
So then the question is how many different wrappers do you have? If it is only a few, then the settings in the configuration file are the way to go. If there are many, that gets tedious. And if there are very many it becomes practically impossible.
So knowing some estimate for how many wrapper sets you have would help.
Even with the wrappers accounted for, it may be that the deadlock and race detectors aren't quite what you need for your problem.
If I understand your issue correctly, you have a queue with limited space, and by accident malformed items don't get cleaned out of the queue, and so the queue gets full and that stalls all processing. While you may have multiple threads involved in this implementation, the issue itself would still be a problem in a basically serial setting.
The best way to work with an issue like this is to try and make a simpler example that displays the same core problem. If you can do this in a way that can be shared with GrammaTech, we can work with you on ways to adjust settings or maybe provide hints to the analysis so it can find this issue.
If you would like to talk about this in more detail, and with prodetction against public disclosure of your code, please contact us at support_at_grammatech_dot_com, where the at and dot should be replaced as needed to make a well formed email address.

Bluetooth gatt connection global variable not changing

I have an issue of an if statement not passing whilst my system gatt connection is not made.
Context
I have a BLE system using a NRF52840-dk board programmed in C. I also have a mobile application which, communicates with this board via a Gatt connection. I have a single service with a single characteristic. I write to this characteristic from my mobile application and, from this do some processing. At the moment I can send over a timestamp and begin storing data. However, I need to then send data back to my mobile device by this connection.
So what I have is a command to be sent from the phone to ask for some data. This should then send data back to the phone by changing the characteristic value.
Before I can change the value I need to see if the command has been issued. However, due to the priorities and constraints of the device I need to do this processing in the main function not in the BLE interrupt that I have done my time stamping in. This is due to the data I will be transmitting eventually will be large.
My issue however is, I receive the command to send some data back to the phone and update a global int value (changed from 0 to 1). Then in my main loop test this value and, if it is 1 write to the terminal and change the value back. I would then use this point of the code to run a function to send the data.
But this statement does not pass.
This is my main loop code
if(GATT_CONNECTED == false)//This works!
{
//Do some functions here
}
else if (GATT_CONNECTED == true)// GATT_CONNECTED = true
{
NRF_LOG_INFO("Test1 passed");//Testing variable this does not print
if(main_test == 1)
{
NRF_LOG_INFO("Test2 passed");//This does not print either irrelevant of value
main_test = 0;//False
}
idle_state_handle();
}
I don't know if the issue is the way I have defined my variable or due to interrupt priorities or something like that. But, when my Gatt connection is made the loop of (GATT_CONNECTED == true) does not seem to process.
My variable is defined in another file where my GATT connection is handled. The GATT connected variable is handled in main. my main_test variable is defined in another c file as int main_test = 0;. In the header declared as extern int main_test;.
I know the GATT_CONNECTED variable works as I have code in it that only runs when my gatt is not connected. I have omitted it for simplicity.
Any ideas,
Thanks
Ps Hope you are all keeping well and, safe
Edit
Added code for simplicity
main.c
bool GATT_CONNECTED = false;
int main(void)
{
Init_Routine();
while(1)
{
Process_data();//This runs if the gatt is not connected if statement inside
if(GATT_CONNECTED == true)//This does not run true when the gatt is connected
{
NRF_LOG_INFO("check gatt connectedpassed");//Testing variable.
nrf_gpio_pin_set(LED_4);//Turn an LED on once led 4 does not work
}
idle_state_handle();
}
}

Apache Prefork/Worker MPM

I'm just beginning to understand how an apache server works, andthe other day I ran into a problem when programming a very simple webpage while displaying a hit count for the page:
/* The simplest HelloWorld module */
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>
static int noOfViews = 0;
static int helloworld_handler(request_rec *r)
{
if (!r->handler || strcmp(r->handler, "helloworld")) {
return DECLINED;
}
if (r->method_number != M_GET) {
return HTTP_METHOD_NOT_ALLOWED;
}
noOfViews++;
ap_set_content_type(r, "text/html;charset=ascii");
ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n",
r);
ap_rputs("<html><head><title>Apache HelloWorld "
"Module</title></head>", r);
ap_rputs("<body><h1>Hello World!</h1>", r);
ap_rputs("<p>This is the Apache HelloWorld module!</p>", r);
ap_rprintf(r, "<p>Views: %d</p>", noOfViews);
ap_rputs("</body></html>", r);
return OK;
}
static void helloworld_hooks(apr_pool_t *pool)
{
ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA helloworld_module = {
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
helloworld_hooks
};
What basically happened is when I would refresh the page, the hit counter would go up, but sometimes it would randomly drop in number. Someone told me that it was because of the way the Apache Prefork MPM worked. After reading this:
http://httpd.apache.org/docs/2.0/mod/prefork.html
I understand the problem more, but I'm still not 100% sure whats going on. So the prefork MPM creates a bunch of child processes, some of them idle, and waits for clients to connect, so when I'm refreshing the page, I'm actually connecting to a bunch of different child processes the server is running. However, this module has a limited number of child processes it can keep up at the same time, so sometimes when it kills a process my counter goes down. I'm not entirely sure if this explanation is correct or why exactly the counter drops.
All advice is appreciated.
Yes, either that or you got one of the other Apache processes to serve you the request when the counter went down.
You could try and configure Apache in such a way that it only spawns exactly 1 child process that lives forever, but by doing that you limit Apaches capabilities.
I recommend that you try and keep your module completely stateless. If you want that hit counter, save the state in a file or a database and retrieve it from there when you need it. You could even talk to another process that has the hit counter just in a static variable like your module at the moment.
You are storing your hit count in the noOfViews variable, which means in the memory of a single process.
Whether under worker or prefork MPM, httpd typically spawns multiple child processes. Each will have its own memory storage for noOfViews, so you are only counting the number of hits for that process. When your request is randomly given to a different process, it has a different counter.
You will notice this more for prefork than worker because each prefork process only handles one request at a time, while worker is threaded and may handle multiple; so there are a lot more processes under prefork than worker. But the same thing will occur under either MPM when your requests are directed to different processes.
Also note that restarting httpd, or just killing individual processes, will lose the counter. New processes will start at a count of 0. So, this is not a good approach if your goal is to count hits globally.

TCP server listen to mulitple clients at once in C

I have written C code for a TCP server to listen to one client at a time.. but I'm having difficulty figuring out how I can get the server to listen to multiple clients at one time.
Does any one know of a good tutorial or example explaining this?
Thanks!
There are a number of ways to achieve this, some of which are:
use select to basically wait on a group of file descriptors until one of them is ready for reading or writing.
use threading, such as pthreads, to hand off individual sessions to separate threads within the one process.
use fork to replicate the process for handling a session, so that the forked process handles that session and the original goes back to waiting for more connections.
Of these, I prefer the middle one. Forking a process is a sometimes-expensive operation in that the data normally has to be copied if either process attempts to change it.
The select option means that your code has to manage multiple sessions and that can sometimes get messy.
With threading, you can separate relatively easily the sessions from each other, without incurring the cost of process duplication. Of course, threading has its own pitfalls if you're not careful but I consider it a preferable option once you understand the potential problem areas.
Take a look at libevent. It powers several popular high-scalability server applications.
Checkout http://www.zeromq.org/
It's a pretty cool networking(or messaging) library that takes 'select' or conventional sockets away from the code.
What platform are you on? If it's Windows, a popular platform API is WaitForMultipleObjectsEx. If it's Linux, popular choices from lower- to higher-level might be select (as mentioned by Joshua), epoll, kqueue, or libevent/libev (similar but slightly different libraries which are among other things abstraction layers upon the preceding APIs).
select is quite portable, but isn't optimal in most cases (a lot has been learned since it was created). Still, if you don't need crazy performance and want to stick to pretty standard C programming, it would be a fine choice, and there is a ton of literature that refers to it. And once your server works with select, it shouldn't be too hard to change it to one of the more advanced multiplexing APIs.
Just create another listener when previous one was taken
see man 2 select
This should do what you want. Beware, untested:
listen_any(int n, int *s, void receiver(int *))
{
FD_SET set;
int x = -1;
int i;
for (i = 0; i < n; ++i)
if (x < s[i]) x= s[i];
while (1) {
FD_ZERO(&set);
for (i = 0; i < n; ++i)
FD_SET(s[i], fd);
select(x, &set, NULL, NULL, NULL);
for (i = 0; i < n; ++i)
if (FD_ISSET(s[i], fd)) {
struct socakddr sa;
int len = sizeof(sa);
int sn = accept(s[i], &sa, &len);
if (sn >= 0) {
if (!receiver(sn))
close(sn);
}
}
}
}
dont know if its anything to do with this but...could use a variant of:
listener.Start()
While True
Dim user As New chatclient(listener.AcceptTcpClient)
End While

Sharing a DNSServiceRef using kDNSServiceFlagsShareConnection stalls my program

I'm building a client using dns-sd api from Bonjour. I notice that there is a flag called kDNSServiceFlagsShareConnection that it is used to share the connection of one DNSServiceRef.
Apple site says
For efficiency, clients that perform many concurrent operations may want to use a single Unix Domain Socket connection with the background daemon, instead of having a separate connection for each independent operation. To use this mode, clients first call DNSServiceCreateConnection(&MainRef) to initialize the main DNSServiceRef. For each subsequent operation that is to share that same connection, the client copies the MainRef, and then passes the address of that copy, setting the ShareConnection flag to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef; it's a copy of an existing DNSServiceRef whose connection information should be reused.
There is even an example that shows how to use the flag. The problem i'm having is when I run the program it stays like waiting for something whenever I call a function with the flag. Here is the code:
DNSServiceErrorType error;
DNSServiceRef MainRef, BrowseRef;
error = DNSServiceCreateConnection(&MainRef);
BrowseRef = MainRef;
//I'm omitting when I check for errors
error = DNSServiceBrowse(&MainRef, kDNSServiceFlagsShareConnection, 0, "_http._tcp", "local", browse_reply, NULL);
// After this call the program stays waiting for I don't know what
//I'm omitting when I check for errors
error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, 0, "_http._tcp", "local", browse_reply, NULL);
//I'm omitting when i check for errors
DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
DNSServiceRefDeallocate(MainRef); // Terminate the shared connection
Any ideas? thoughts? suggestion?
Since there are conflicting answers, I dug up the source - annotations by me.
// If sharing...
if (flags & kDNSServiceFlagsShareConnection)
{
// There must be something to share (can't use this on the first call)
if (!*ref)
{
return kDNSServiceErr_BadParam;
}
// Ref must look valid (specifically, ref->fd)
if (!DNSServiceRefValid(*ref) ||
// Most operations cannot be shared.
((*ref)->op != connection_request &&
(*ref)->op != connection_delegate_request) ||
// When sharing, pass the ref from the original call.
(*ref)->primary)
{
return kDNSServiceErr_BadReference;
}
The primary fiels is explained elsewhere:
// When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
// For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
// For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
The problem with the question is that DNSServiceBrowse maps to ref->op==browse_request which causes a kDNSServiceErr_BadReference.
It looks like kDNSServiceFlagsShareConnection is half-implemented, because I've also seen cases in which it works - this source was found by tracing back when it didn't work.
Service referenses for browsing and resolving may unfortunately not be shared. See the comments in the Bonjour documentation for the kDNSServiceFlagsShareConnection-flag. Since you only browse twice I would just let them have separate service-refs instead.
So both DNSServiceBrowse() and DNSServiceResolve() require an unallocated service-ref as first parameter.
I can't explain why your program chokes though. The first DNSServiceBrowse() call in your example should return immediately with an error code.
Although an old question, but it should help people looking around for answers now.
The answer by vidtige is incorrect, the may be shared for any operation, provided you pass the 'kDNSServiceFlagsShareConnection' flag along with the arguments. Sample below -
m_dnsrefsearch = m_dnsservice;
DNSServiceErrorType mdnserr = DNSServiceBrowse(&m_dnsrefsearch,kDNSServiceFlagsShareConnection,0,
"_workstation._tcp",NULL,
DNSServiceBrowseReplyCallback,NULL);
Reference - http://osxr.org/android/source/external/mdnsresponder/mDNSShared/dns_sd.h#0267

Resources