Aviv Heller (avheller | 21 Aug 15:33 2014
Picon

Timers expire prior to expiry time

Hi,

I have encountered a problem, on version 4.11 of the library, where a timer started expired prior to its intended expiry time.

This happened because time_update() is not called by ev_timer_start() prior to calculating the expiry timestamp, which in cases where a timer is started after a long processing time during a loop iteration, results in ev_timer_start() using an old time instead of the current one.

In cases where the system is under heavy load (a prevalent case in embedded systems), this problem can manifest even if the iteration processing time prior to setting the timer is in theory short.

The fix I propose is to have ev_timer_start() call time_update() before calculating the expiry timestamp (patch attached).

I would be glad to know what are your thoughts on this issue, and whether this fix is needed and makes sense.

Thanks,
Aviv

Attachment (libev-time-update-on-timer-start.patch): application/octet-stream, 738 bytes
_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Hongli Lai | 4 Aug 09:02 2014
Picon

Patch: fix libeio cancellation

According to the libeio documentation, the callback will still be
called even if the request has been cancelled. The libeio code checks
for the cancel flag, and does not call the callback if it's set. This
happens even if the system call has already finished.

The attached patch fixes the problem.

--

-- 
Phusion | Web Application deployment, scaling, and monitoring solutions

Web: http://www.phusion.nl/
E-mail: info <at> phusion.nl
Chamber of commerce no: 08173483 (The Netherlands)
Attachment (fix_eio_cancel.patch): application/octet-stream, 474 bytes
_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Fw Lei | 27 Jul 06:59 2014

Can I use ev_async in multiprocess context?

The document of libev gave examples for signal and thread context.

But I want use multiprocess model, in my opinion just put ev_loop and all
watches in shared memory, that will be OK.

My question is, how can I put the default ev_loop into shared memory?

Thanks.
Ramana Yarlagadda | 26 Jun 01:10 2014
Picon

read event is not getting triggered

Hi,

I am using libev in one of my client software module. Client connects to the server. Server sends some information in response to client request.

One of the problems i am seeing here is client socket Event is not getting triggered when the data is available on the client socket.

I know for sure that the server has sent the information requested by the client. So, just to prove that in a timer callback i called the getdata() on the client socket. The getdata() received data on the client socket.

When we send the kill signal we do receive data or the event call back gets triggered.

Has anybody seen similar issue?  can somebody help me here to find a solution.

Following is the skeleton of the client program.

-thanks in advance
-ramana
      
class Client {
    void run();

private:
    AMQPWrapper ipc_;
    ev::io io_;
    ev::sig sio_;
    ev::timer timer_;
};

Client::run{

    ev::default_loop loop;

    timer_.set<Client, &Client::cb_timerEvent>(this);
    timer_.start(1, 0);

    io_.set<Client, &Client::cb_sockEvent>(this);
    io_.start(ipc_.getSocketFD(), ev::READ);

    sio_.set<&Client::cb_signal>();
    sio_.start(SIGINT);

    sendRequest();

    loop.run(0);
}

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Nick Zavaritsky | 28 May 08:43 2014
Picon

Re: ev_io mode switching performance

Hi!

> Well, obviously, you need to call a function or macro every time you toggle
> the flags.
> 
> Apart from that, it doesn't matter whether you toggle once or many times per
> event loop iteration - when libev polls for new events, it will tell the
> backend about them.
> 
> For select and poll, the overhead is trivial, for kqueue and epoll, its
> nontrivial and even partially depends on outside events. In the worst
> case, it is one extra syscall per fd with epoll, in the best case, the
> overhead is trivial with epoll.

Thanks a lot!

I am most interested in the epoll backend. Does libev issue a epoll_ctl() for every
io watcher that changed mode in the last iteration or the behavior is somewhat
more sophisticated (i.e. no epoll_ctl() when the ‘initial’ and ‘final’
modes were the same)?
Jan Kaluža | 16 May 08:55 2014
Picon

Missing dual-licensing in ecb.h

Hi,

while packaging libeio for Fedora, I have found out that ecb.h is 
missing GPLv2 part of the license. Is that intentional or you forgot it 
there?

Regards,
Jan Kaluza
Laska Radek | 6 May 10:43 2014
Picon

The special problem of time updates

Hi,

I have questions about  The special problem of time updates (see
http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem
_of_time_updates):

1) There is example in documentation how avoid this. Is this example
correct? I think there should be:
  ev_timer_set (&timer, after  +  (ev_time () - ev_now () ), 0.);
  instead of:
  ev_timer_set (&timer, after + ev_now () - ev_time (), 0.);

2)  It will be nice add ev_time to C++ wrapper (ev++.h). Is it possible
in next version?

Thanks,
Radek Laska
Christian Parpart | 2 May 16:12 2014
Picon

libev, multiple threads, and ev_async as notification vs valgrind/helgrind

Hey all,

I am trying to find a race in my threaded app, so I decided to give valgrind+helgrind a try.

My app is spawning N worker threads. each has its own event loop and nicely runs in parallel.
Sometimes one worker needs to wakeup another worker in order to make sure it knows
about something, so I use ev_async_send() for this.

However, even though the man page states (unless I am misreading it) that ev_async is
for this very purpose and is thread safe without any further doing, I get tons of
messages by Valgrind's tool "helgrind" about possible data races.

The race basically occures inside ev_async_send() in thread A, a read operation that is said to
be in conflict to a prior read in the same data region happened inside ev_invoke_pending()+... in thread B.


The Valgrind output about the data race looks like this:

==5023== Possible data race during write of size 4 at 0x76DBB68 by thread #1                                                                                               

==5023== Locks held: 1, at address 0x76B9968
==5023==    at 0x6BBAD70: ev_async_send (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x50E6E28: ev::async::send() (ev++.h:798)
==5023==    by 0x5110D8F: x0::HttpWorker::enqueue(std::pair<x0::Socket*, x0::ServerSocket*>&&) (HttpWorker.cpp:197)
==5023==    by 0x510AAD8: x0::HttpServer::onNewConnection(x0::Socket*, x0::ServerSocket*) (HttpServer.cpp:145)
==5023==    by 0x510D520: void x0::ServerSocket::callback_thunk<x0::HttpServer, &x0::HttpServer::onNewConnection>(x0::Socket*, x0::ServerSocket*) (ServerSocket.h:130)
==5023==    by 0x4E802EC: x0::ServerSocket::acceptOne() (ServerSocket.cpp:705)
==5023==    by 0x4E7F9E9: x0::ServerSocket::accept(ev::io&, int) (ServerSocket.cpp:665)
==5023==    by 0x4E803C2: void ev::base<ev_io, ev::io>::method_thunk<x0::ServerSocket, &x0::ServerSocket::accept>(ev_loop*, ev_io*, int) (ev++.h:479)
==5023==    by 0x6BB5E44: ev_invoke_pending (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x510FE34: x0::HttpWorker::invoke_pending(ev_loop*) (HttpWorker.cpp:51)
==5023==    by 0x6BB8FE6: ev_run (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x5110A3A: ev_loop(ev_loop*, int) (ev.h:826)
==5023==    by 0x51109B2: x0::HttpWorker::run() (HttpWorker.cpp:157)
==5023==    by 0x510ABE3: x0::HttpServer::run() (HttpServer.cpp:225)
==5023==    by 0x4734BD: x0d::XzeroDaemon::run() (XzeroDaemon.cpp:289)
==5023==    by 0x492915: main (x0d.cpp:16)
==5023== 
==5023== This conflicts with a previous read of size 4 by thread #2
==5023== Locks held: 1, at address 0x76DAC28
==5023==    at 0x6BB6BF5: ??? (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x6BB5E44: ev_invoke_pending (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x510FE34: x0::HttpWorker::invoke_pending(ev_loop*) (HttpWorker.cpp:51)
==5023==    by 0x6BB8FE6: ev_run (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==5023==    by 0x5110A3A: ev_loop(ev_loop*, int) (ev.h:826)
==5023==    by 0x51109B2: x0::HttpWorker::run() (HttpWorker.cpp:157)
==5023==    by 0x5110474: x0::HttpWorker::_run(void*) (HttpWorker.cpp:141)
==5023==    by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)

I hope somebody can tell me that this is a false positive or what I might be missing.

From what I can think of, I should not need any locks at for my threading model, there watchers are only modified inside their respective worker threads *except* the fact, that ev_async is used to notify thread A to thread B to wake up and do some work.

As you may see in the backtrace, I also tried to add a lock around struct ev_loop uses, as shown in the example of the libev man page, in the hope, that maybe I need that part there anyways, but appearently that didn't fix it either.

Any ideas?

Many thanks in advance,
Christian Parpart.
_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Nick Zavaritsky | 1 May 23:19 2014
Picon

Libev: embeding within a 'foreign' event loop

Hi!

I realy love the flexibility and the great design of libev, however I am a bit puzzled with the
event loop embeding.

The problem is that I want to mix and match code that uses libev event loop with the code
tailored for a very different event loop environment, all in the same thread.

This other event loop environment is actually Nginx web server. The reason I am willing to jump
through hoops is because of the piece of code that is to be used both in a standalone utility and
in a Nginx module.

Nginx event loop provides utilities to watch file descriptors for status changes. Timers are also
included. It's safe to assume that epoll is used for fd watching on the target platform.

I think it is relatively easy to embed nginx event loop inside ev_loop with but the pair of watchers:
ev_io for the epoll fd plus ev_timer (or maybe ev_prepare and ev_check should be added to the mix
as well?)

There is one thing that still bothers me: now it takes two epoll_wait() calls for Nginx to fetch the events
instead of one. (One epoll_wait() in libev plus another epoll_wait() for the nested epoll fd maintained
solely by Nginx). Though the overhead is probably negligible I would prefer to have it another
way around, i.e. let Nginx control the 'outermost' event loop while libev drives the embeded loop.

Is this possible with libev?

For example libuv has uv_backend_fd() and uv_backend_timeout(); but I can't find anything
similar in libev.
李晓岚 | 1 May 10:33 2014
Picon

Fork watcher will not be called if fork() is invoked in prepare watcher callback.

Hi, there,
Considering this scenario, loop_init called without EVFLAG_FORKCHECK,
then register some fork and prepare watchers and start them. At a
certain point, in prepare watcher callback fork() is called, and in
child process ev_loop_fork() is also called honestly. Oops, the
callbacks of fork watcher will never be fired.
According to the source code, ev_loop_fork() just set a flag
postfork=1, and the following loop_fork() call clears this flag before
the next loop until which fork watchers are examined.
Is this behavior is intended with any considerations or a bug?
Assaf Inbal | 25 Apr 14:34 2014
Picon

Re: libev doesn't notify on read event (file FD and timers)

> I'll take care of it, but indeed, that's the code that generates the
> event.  It does rely on the undocumented behaviour of EPOLL returning
> eperm on regular files (but whats not undocumented in epoll...), but the
> problem is caused by your watchers using the same fd, and while libev
> removes the emulation for the fd on the first ev_io_stop, it doesn't add
> it back on the next ev_io_start, which is a bug in not clearing the epoll
> event mask (EV_EMASK_EPERM).

Just one more question, if the issue is because the mask isn't cleared
for the FD, why does it work without the timer in the sample code I
attached before, I still call ev_io_stop on the first FD, and then
ev_io_start on the next.

Gmane