Iam looking to write a socket program based on libev. I noticed that several examples as stated in https://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-server.c use the call backs based on init. For example,
main() {
......
ev_io_init(&client.io, client_cb, client.fd, EV_READ|EV_WRITE);
ev_io_start(EV_A_ &server.io);
}
static void client_cb (EV_P_ ev_io *w, int revents)
{
if (revents & EV_READ)
{
....
} else if (revents & EV_WRITE) {
......
}
}
My question comes from the expected behaviour, say for example, all that i read when in EV_READ is stored in a linked list. Lets say I keep getting free flow of packets to read, will i ever get a chance to get into EV_WRITE? I have to send out all that I recv through read to another socket. So Will it be once EV_READ and second time EV_WRITE? In other words when will EV_WRITE be unblocked? Or do I need to block EV_READ for EV_WRITE to be called. Can someone help me understand this?
I think you should keep write callback separated from read callback:
main() {
ev_io_init(&read.io, read_cb, client.fd, EV_READ);
ev_io_init(&write.io, writead_cb, client.fd, EV_WRITE);
ev_io_start(EV_A_ &read.io);
ev_io_start(EV_A_ &write.io);
}
This is my solution.
To answer shortly: If you allways check for one type of event first and then have an else
if for the other you risk starvation. In general I would check for both, unless the specified protocol made it impossible for both to be activated at the same time.
Here is a more iffy answer:
The link in your question does not contain a code structure such as your question. The client https://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-client.c does have a similar callback. You will notice it disables write events, when it has written once.
// once the data is sent, stop notifications that
// data can be sent until there is actually more
// data to send
ev_io_stop(EV_A_ &send_w);
ev_io_set(&send_w, remote_fd, EV_READ);
ev_io_start(EV_A_ &send_w);
That looks like an attempt to avoid starvation of the pipe READ event branch. Even though Im not very familiar with libev, the github examples you linked to do not seem very robust. E.g static void stdin_cb (EV_P_ ev_io *w, int revents)does not use the return value of getline() to detect EOF. Also the send() and recv() socket operation return values are not inspected for how much was read or written (though on local named pipe streams the amounts will most likely match the amounts that were requested). If this was later changed to a TCP based connection, checking the amounts would be vital.
Related
I'm learning c and messing around with xcb lib (instead of X11) on a raspberry pi4.
The problem is that when implementing the events loop with xcb_poll_for_event instead of xcb_wait_for_event, one core of four is 100% full. What am I doing wrong? And is there any benefit of using wait_for_event (blocking way) instead of xcb_poll_for_event(non blocking)?
The goal is to create a window where the user interact with keyboard/mouse/gamepad on objects, like a game. Can anyone give a hand?
The relevant code is:
int window_loop_test(xcb_connection_t *connection, Display *display){
/* window loop non blocked waiting for events */
int running = 1;
while (running) {
xcb_generic_event_t *event = xcb_poll_for_event(connection);
if (event) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE: {
// TODO
break;
}
case XCB_KEY_PRESS: {
/* Quit on 'q' key press */
/* write key pressed on console */
const xcb_key_press_event_t *press =
(xcb_key_press_event_t *)event;
XKeyEvent keyev;
keyev.display = display;
keyev.keycode = press->detail;
keyev.state = press->state;
char key[32];
XLookupString(&keyev, key, sizeof(key) - 1, NULL, NULL);
// key[len] = 0;
printf("Key pressed: %s\n", key);
printf("Mod state: %d\n", keyev.state);
if (*key == 'q')
running = 0;
break;
}
}
free(event);
}
}
return 0;
}
Polling and waiting each have their advantages and are good for different situations. Neither is "wrong" per se, but you need to use the correct one for your specific use case.
xcb_wait_for_event(connection) is a blocking call. The call will not return until an event is available, and the return value is is that event (unless an error occurs). It is good for situations where you only want the thread to respond to events, but otherwise not do anything. In that case, there is no need to spend CPU resources when no events are coming in.
xcb_poll_for_event(connection) is a non-blocking call. The call always returns immediately, but the result will be NULL if no event is available. It is good for situations where you want the thread to be able to do useful work even if no events are coming in. As you found out, it's not good if the thread only needs to respond to events, as it can consume CPU resources unnecessarily.
You mention that your goal is to create a game or something similar. Given that there are many ways to architect a game, either function can be suitable. But there are a couple of basic things to keep in mind that will determine which function you want to use. There may be other considerations as well, but this will give you an idea of what to look out for.
First of all, is your input system running on the same thread as other systems (simulation, rendering, etc)? If so, it's probably important to keep that thread available for work other than waiting for input events. In this case, xcb_poll_for_event() is almost required, otherwise your thread will be blocked until an event comes in. However, if your input system is on its own thread that doesn't block your other threads, it may be acceptable to use xcb_wait_for_event() and let that thread sleep when no events are coming in.
The second consideration is how quickly you need to respond to input events. There's often a delay in waking up a thread, so if fast response times are important you'll want to avoid letting the thread sleep in the first place. Again, xcb_poll_for_event() will be your friend in this case. If response times are not critical, xcb_wait_for_events() is an option.
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.
Now I'm learning Bidirectional streaming in asynchronous GRPC++.
Thanks for the master:https://github.com/Mityuha/grpc_async. I get much useful information to know the realization principle of this mode.But I have a question about it:
Not much to say,the code is following:
the server:
if(!ok || mcounter >= greeting.size())//ctx_.IsCancelled() doesn't work
{
std::cout << "[ProceedMM]: Trying finish" << std::endl;
status_ = FINISH;
responder_.Finish(Status(), (void*)this);
}
the client:
void AsyncCompleteRpc()
{
void* got_tag;
bool ok = false;
while(cq_.Next(&got_tag, &ok))
{
AbstractAsyncClientCall* call = static_cast<AbstractAsyncClientCall*>(got_tag);
call->Proceed(ok);
}
std::cout << "Completion queue is shutting down." << std::endl;
}
in this server,the end of ClientStream is judged by the bool value of OK which is send by client.It isn't similar to the way of synchronous GRPC,which is judged the steaming end by the return of bool Read(RequestType* request) in the class of ServerReaderWriter in many times.It's so strange to find the same way in the class of ServerAsyncReaderWriter which is void Read(R* msg, void* tag).Though I know it's because of the asynchronous way.But if I don't know how much times of asynchronous streaming without the judgement of "OK", how to find the way like synchronous streaming to judge the end of client streaming.Because I test the performance by java which is the same code between synchronous with asynchronous ways,which don't have the bool value of OK in asynchronous ways.
So can someone help me?Or tell me some ways to deal with it or find a way to test the performance testing of GRPC++ by Bazel of in my another question.
I'm not 100% sure that I get the question, but what ok tells you is (when false) that the operation you requested couldn't be completed and nothing else will ever complete successfully on that side of the stream. So if you issue a Read operation and the Next gives you a !ok value, then you can be sure that no more data will ever come back from the client. A more detailed explanation is given in the comments for the CompletionQueue class.
Thanks and good luck with gRPC.
In the case of receiving a stream in an asynchronous client of gRPC, you will use a ClientAsyncReader<> class to receive data. This class differs when both send and receive are stream, but logic is the same.
This class has a Finish() method which you need to call after finishing sending your rpc data to server. When answer stream from server is finished, a message to CompletionQueue will be added which corresponds to this method. This Finish method returns final status when its message is returned in CQ. You can find out that your stream is finished. Your code will be similar to this:
response_reader_ = stub->PrepareAsyncXYZ(ctx_, req, cq);
response_reader_->StartCall(&start_data_);
response_reader_->Finish(&status_, &finish_data_);
in this sample, message in CQ will have finish_data_ tag and you can use it to handle it properly. You will probably will need to manage messages for Finish() and Read() by reference counting, because you will probably get an additional failed read message too. when message with finish_data_ is received in CQ, status_ will have the valid value of status.
At least it is how I wrote it.
When trying to use a callback function for a DBus reply I get stuck on creating a good/well working main loop.
What I want to do is simple, make a DBus call and specify a function which should be called when the reply comes. This is because I do not want to block my thread for the whole time until a reply has been calculated and arrived.
I first use dbus_connection_send_with_reply(..) to get a DBusPendingCall, then i specify a callback function using dbus_pending_call_set_notify(..). Before doing this, when connecting to the bus, I have started another thread which should wait for a response and call the callback functions. I have found no examples at all and no very good documentation of how I should design a dbus main-loop like this. I have tried:
// Main dbus loop handling data transfer and callbacks..
void *dbus_main(void *args)
{
my_dbus dbus = (my_dbus)args;
while (MY_DBUS_STATUS_STOPPING != dbus->status
&& dbus_connection_read_write_dispatch(dbus->conn, -1))
;
return 0;
}
// Start the dbus main loop in a new thread
void dbus_main_start(my_dbus dbus) {
if (!pthread_create(&dbus->th, NULL, dbus_main, dbus)) {
// PRINT ERROR
}
}
My problem is two things:
I try to stop the app by setting the dbus->status flag to MY_DBUS_STATUS_STOPPING and waiting for the threads to join. This does not work if the thread is blocked in the dbus_connection_read_write_dispatch(..) function. If i want the app to stop fast then I need to specify a very short timeout. Can't I wake the blocked thread in some other way?
More seriously, with this code i don't get any callback from the method I call. If I add some fprintf(..) to write to stdout I might suddenly get my callback. It seems quite random, so maybe some kind of deadlock? I have tried having a dbus_connection_flush(..) between sending the message and adding the callback with _set_notify(..) function. Doesn't do any difference... But printing some letters to stdout in the same place fixes the problem. Printing to stdout in the dbus-main-loop insted of an empty ";" seems to do the trick sometimes...
So anyone who has an example of using the low-level dbus api together with async methods, ie not using _block(..)??
You can create a simple DBus application as follows...
To setup a server to handle incoming messages, call dbus_connection_register_object_path passing in a VTable containing function pointers to handle the messages. Such as:
{ .unregister_function = UnregisteredMessage, .message_function = ServiceMessage }
To send a new message, call dbus_connection_send_with_reply and then dbus_pending_call_set_notify to associate a callback function to handle the reply.
Next you will need to service DBus. This can be done in a separate thread or by calling periodically with non-blocking calls in the same thread, as shown below:
/* Non-blocking read of the next available message */
dbus_connection_read_write ( MyDBusConnection, 0 ) ;
while ( dbus_connection_get_dispatch_status ( MyDBusConnection ) == DBUS_DISPATCH_DATA_REMAINS )
{
dbus_connection_dispatch ( MyDBusConnection ) ;
}
There are some good example of using the DBUS C API here: http://www.matthew.ath.cx/misc/dbus
It is highly recommended that you use a D-Bus library other than libdbus, as libdbus is fiddly to use correctly, as you are finding. If possible, use GDBus or QtDBus instead, as they are much higher-level bindings which are easier to use. If you need a lower-level binding, sd-bus is more modern than libdbus.
If you use GDBus, you can use GMainLoop to implement a main loop. If you use sd-bus, you can use sd-event.
I have a piece of MPI C code which looks something like the following:
for(i=0;i<NTask;i++)
{
got_initial_bit_of_data[i]=0;
if(need_to_communicate with i)
MPI_ISend(&bit_of_pre_data_for_i,1,MPI_INT,partner,0,MPI_COMM_WORLD,&pre_requests[i]);
}
while(1)
{
MPI_Testsome(NTask,pre_requests,&ndone,idxs,MPI_STATUSES_IGNORE)
if(ndone)
{
for(i=0;i<ndone;i++)
{
MPI_ISend(&the_main_block_of_data_for_i,size_of_block,MPI_BYTE,idxs[i],1,MPI_COMM_WORLD,&main_requests[idxs[i]]);
}
}
//Other stuff that doesn't matter
MPI_IProbe(MPI_ANY_SOURCE,0,MPI_COMM_WORLD,&flag,&status);
if(!flag)
{
MPI_IProbe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&flag,&status);
}
if(flag)
{
//Receiving the initial little bit of data
if(status.MPI_TAG==0)
{
//Location 1
got_initial_bit_of_data[status.MPI_SOURCE]=1;
MPI_Recv(&useful_location,1,MPI_INT,status.MPI_SOURCE,MPI_STATUS_IGNORE);
}
//Receiving the main bit of data
else if(status.MPI_TAG==1)
{
//Location 2
if(got_initial_bit_of_data[status.MPI_SOURCE]!=1)
//Something has gone horribly wrong...
//Receive the main bit of data here...
}
}
}
Obviously I've omitted lots of details because the full code is several hundreds of lines long. If something I've done looks a bit odd, it's probably because it is because of something in the omitted code block.
The idea is that at the start each processor sends an "announcement" message to those processors it wants to talk to. When it detects that those processors have received this message (that is when MPI_Testsome indicates the "announcement" MPI_Isend is complete), it should send a big chunk of data.
From the point of view of a processor receiving data, it should first receive the announcement message at location 1, which will cause MPI_Testsome to indicate that the Isend is complete and send the big chunk of data. The receiving processor should then receive the main block of data at location 2. Following this logic, it should be impossible to reach location 2 with got_initial_bit_of_data[status.MPI_SOURCE] being 0, but this is precisely what does happen very occasionally and I'd like to work out why.
Either I've got the logic of the code wrong, or there's some subtlety of IProbe and Testsome that I'm missing.
I'm also exiting and re-entering this entire block of code, with different processors moving in and out at different points in time, but only when all their ISends have been processed (as determined by Testsome saying that they're completed).
If the above explanation doesn't make any sense, what I want to know is are there any circumstances under which Testsome claim that an ISend is completed without the matching receive completing (or even starting)? Is a processor making a call to IProbe enough to cause Testsome to consider a request completed for instance?
If the above explanation doesn't make any sense, what I want to know is are there any circumstances under which Testsome claim that an ISend is completed without the matching receive completing (or even starting)? Is a processor making a call to IProbe enough to cause Testsome to consider a request completed for instance?
All that MPI_Testsome guarantees is that the buffer you were using from ISend is no longer needed by MPI. If you want to guarantee that the recipient has started the receive, use the synchronous form, ISSend.