Morand, Guy | 6 Jul 15:09 2015
Picon

EXCEPTION and POLLPRI events

Hello libev developpers!

I'm writing a little application to monitor GPIO status on my embedded Linux device. I wanted to give libev a
try, on the paper it looks really cool and fast.

However, to monitor a GPIO line, I need to get the  EXCEPTION event from select or the POLLPRI from poll.
Unfortunately this event doesn't seem to be implemented in libev and I can't use it out of the box. 

Before trying to change something, I wanted to see with you if there is there any reasons for no implementing
this event? What are the constraints and the limitations?

Kind regards,

Guy Morand

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev
Picon

Questions - partly newbie

Hi all

I'm new to event loops and am wondering about a couple of things...
Maybe somebody will clarify the questions for me. I'm using ev++ for 
implementation, if this is of interest.

I'm implementing a TCP-Socket Server on Linux to which a large number of 
embedded devices is connecting and reporting status every 10-60sec.

The current architecture spawns a thread for the server, accepting 
connections in an own ev::default_loop.
The server there is 2x ev:signal and 1x ev::io(ev::READ) for accepting 
connections.

On accepting the client gets it's own thread with an ev::dynamic_loop.
For the client I'm using 2x ev::io (1x ev::READ, 1x ev::WRITE), 1x 
ev::timer, 1x ev::async for stopping.

1. When running an event loop with multiple watchers, per iteration only 
one watcher is called - is this intended or is my implementation wrong?

2. Having the ev::timer running, at some point the ev::io watchers stop 
working. are the watcher excluding each other?

3. Sometimes the latency is extremly high, when accepting connections. I 
can't really find a reason for this. Any hints?

4. Is there any known difference between ev++ and ev I should be caring 
about?

(Continue reading)

Dejan Markic | 22 May 15:26 2015

Some questions about libev

Hello!

I'm writing multi-threaded C client with hiredis and their libev adapter. I'm using multi-threading,
because I have several servers to which I send the same command and await their reply.

First of all, there is no ev default loop. Each ev loop is initialized in main thread and is then passed on to
pthread_create (along with other stuff like watchers, etc). 
Once the thread starts, it create hiredis async handler and attaches libev with its libev handler and sets
up all the callbacks.
After all is initialized and connected, I send commands from main thread to all servers via redisAsyncCommand.

Questions:

1. Hiredis libev adapter uses two ev_io watchers, one for reading and one for writing. It's simply calling
start and stop on those watchers based on what it tries to do.
    This does not work for me, unless I register another ev_async watcher, that fires everytime hiredis tries
to start/stop the io_watcher. Is that expected? I would say that once
    libev goes into poll/select/etc wait, it will not move out of wait if you stop the watcher, or start the
stopped watcher, right?

2. I tried another approach I saw on the internet. Single ev_io watcher, but everytime hiredis tries to
stop/start read/write, I to ev_io_stop(...) and then I set EV_READ and/or EV_WRITE flags via ev_io_set
and then ev_io_start again. Also in that case, I need ev_async watcher to wakeup the libev. Would you that
that single IO watcher approach would be better?

Both 1. and 2. I tried protecting changes in watchers with mutex, but no success. 

3. My test program hangs after few minutes, maybe even few seconds (it's working for atleast 1000
iterations, even 100000 sometimes) after I fire it (sending SET/GET to one or many servers). It hangs in
epoll_wait or select (tried different EVBACKEND_*). It doesn't receive the ev_async event it seems. I
(Continue reading)

Marc Lehmann | 22 May 09:49 2015
Picon

Re: ev_periodic like functionality for time intervals

On Wed, May 20, 2015 at 11:57:31PM +0200, Thilo Schulz <thilo <at> tjps.eu> wrote:
> > The most compatible/conceptually simple solution would be to simply have
> > a one-minute timer or so and check for the interval yourself, which might
> 
> Hmm, time jumps will only be the exception that I want to catch if they 
> happen. I still want to trigger on entering the interval as soon as possible, 
> so to have a second watcher, a timer watcher in addition to the periodic is a 
> bit ugly in my opinion.

No, this suggestion was really only having one ev_timer, and checking for
interval crossings inside, you wouldn't have an extra ev_periodic watcher:

   int on;

   timer_callback (...)
   {
      int hour = get_hour ();

      int new_on = hour < 10 || hour > 22;

      if (new_on != on)
        {
          on = new_on;
          state changed!
        }
  }

It's the simple hack that I wouldn't use if you use if you had many of
these.

(Continue reading)

Andrey Pokrovskiy | 22 May 06:43 2015
Picon

Strict aliasing rule strikes back

Hi,

When I include ev.h in my c++ code (gcc 4.9, -std=c++11 -Wall -Wextra
-Werror -pedantic-errors -O3) I get strict aliasing warning.

But I'm not saying that there is something wrong with libev and that
those warnings should be fixed asap (surprise-surprise).

I'm just curious why libev needs all those casts that produce that
warning in a first place. For example, why not to have it that way:

#define ev_init(ev,cb_) do {                   \
-  ((ev_watcher *)(void *)(ev))->active  =      \
-  ((ev_watcher *)(void *)(ev))->pending = 0;   \
+  (ev)->active  = \
+  (ev)->pending = 0;   \
  ev_set_priority ((ev), 0);                   \
  ev_set_cb ((ev), cb_);                       \
  ev_set_cb ((ev), cb_);                               \
} while (0)

Since ev must be a watcher, it will have "active" and "pending"
members and two-steps cast is not really necessary. Another example:

-# define ev_set_cb(ev,cb_)                   (ev_cb_ (ev) = (cb_), memmove (&
                          ((ev_watcher *)(ev))->cb, &ev_cb_ (ev),
sizeof (ev_cb_ (ev))))
+# define ev_set_cb(ev,cb_)                   (ev)->cb = (cb_)

Why to use memmove when "ev->cb" and "cb_" must have the same type and
(Continue reading)

Thilo Schulz | 20 May 04:06 2015
Picon

ev_periodic like functionality for time intervals

Dear list, der Mr. Lehman,

for my program, I need some kind of output variable which shall have two 
states depending on wall clock time:

- 22:00 to 10:00: off
- 10:00 to 22:00 on

and a callback that is to be called upon change of this state.
An ev_periodic watcher seems to be ideal here.
If I understand the documentation correct, a state change would be detected 
if, for instance, PC time jumps from, say
2015-05-19 13:00:00 to 2015-05-19 23:00:00
but not if PC time jumps backwards like
2015-05-19 23:00:00 to 2015-05-18 13:00:00
which is of course undesirable.

I guess in the latter case, I will need to detect a time jump backwards by, 
for instance, comparing the return value of ev_now() with the return value of 
ev_now() from a previous event loop iteration in an ev_check watcher.

Just want to avoid any unpleasant surprises.

Best regards,
Thilo Schulz

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
(Continue reading)

Marc Lehmann | 13 May 05:34 2015
Picon

Re: Nanosecond timestamps for ev_stat

On Tue, May 12, 2015 at 05:59:33PM +0300, Roman Tsisyk <roman <at> tarantool.org> wrote:
> I made a patch to add support for nanosecond timestamps in ev_stat.
> Please review and consider to merge.

Hi, thanks for the patch, but I am afraid it isn't so simple.

While providing nanosecond resulitioon if possible is one of our goals, too,
we haven't found a way to make it possible.

Simply making the ev_stat internal test a bit more sensitive without being
able to tell the user of ev_stat does not allow the libev user to make active
use of this feature - the user still has to assumer there is only the
standard one second resolution, both because that might be the actual
filesystem resolution, and libev might not have tested this at all.

To put it differently - the libev user has to cope with one second
resolution, whether libev was compiled to compare nanoseconds or not.

There are other problems, for example, on GNU/Linux for some inexplicable
reason only has a 32 bit struct stat by default, when basically everybody
else supports 64 bit, which makes libev incompatible to programs compiled
in the nonstandard (on gnu/linux) lfs environnment.

I think the only workable solution is to replace the rather fuzzy struct
stat by some ev_stat struct that has ev_stamp members for the times, in
which higher resolution timestamps could be stored, and/or always provide
the full nanosecond resolution, independent of compilatzion environment
and compilation method.

Also, the detection for the struct member availability should work without
(Continue reading)

Jie Liu | 6 May 18:45 2015
Picon

How does array_needsize macro work?

When I'm reading the code of libev, I find this definition of "array_needsize":

#define array_needsize(type,base,cur,cnt,init)            \
  if (expect_false ((cnt) > (cur)))                \
    {                                \
      int ecb_unused ocur_ = (cur);                    \
      (base) = (type *)array_realloc                \
         (sizeof (type), (base), &(cur), (cnt));        \
      init ((base) + (ocur_), (cur) - ocur_);            \
    }

According to the comments, memories are allocated in chunks of "MALLOC_ROUND". It is possible that the size needed is larger than "MALLOC_ROUND". In this case, the "array_needsize" may not allocate enough memories because it is using "if" instead of "while". I though there would be a "while" loop but I didn't find it. The library is proved by many projects, so I must miss something here. Could anyone point out how it works?

Thanks,
Jie

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Orion Poplawski | 22 Apr 23:31 2015

passenger's modification to libeio

phusion passenger 5.0.6 ships a modified libeio 4.15.  Fedora builds it
against system libeio, so this fails due to missing symbols.  The full diff is:

diff -ru ../libev/libev-4.15/ev.c passenger-5.0.6/ext/libev/ev.c
--- ../libev/libev-4.15/ev.c    2013-03-01 04:10:48.000000000 -0700
+++ passenger-5.0.6/ext/libev/ev.c      2013-10-26 16:00:00.000000000 -0600
 <at>  <at>  -967,7 +967,7  <at>  <at> 
   #define ecb_unreachable() __builtin_unreachable ()
 #else
   /* this seems to work fine, but gcc always emits a warning for it :/ */
-  ecb_inline void ecb_unreachable (void) ecb_noreturn;
+  ecb_inline ecb_noreturn void ecb_unreachable (void);
   ecb_inline void ecb_unreachable (void) { }
 #endif

 <at>  <at>  -2477,6 +2477,18  <at>  <at> 
   return backend;
 }

+int
+ev_backend_fd (EV_P) EV_THROW
+{
+  return backend_fd;
+}
+
+int
+ev_loop_get_pipe (EV_P_ unsigned int index) EV_THROW
+{
+  return evpipe[index];
+}
+
 #if EV_FEATURE_API
 unsigned int
 ev_iteration (EV_P) EV_THROW
diff -ru ../libev/libev-4.15/ev.h passenger-5.0.6/ext/libev/ev.h
--- ../libev/libev-4.15/ev.h    2013-03-01 04:05:29.000000000 -0700
+++ passenger-5.0.6/ext/libev/ev.h      2013-10-26 16:00:00.000000000 -0600
 <at>  <at>  -605,6 +605,9  <at>  <at> 

 EV_API_DECL unsigned int ev_backend (EV_P) EV_THROW; /* backend in use by loop */

+EV_API_DECL int ev_backend_fd (EV_P) EV_THROW;
+EV_API_DECL int ev_loop_get_pipe (EV_P_ unsigned int index) EV_THROW;
+
 EV_API_DECL void ev_now_update (EV_P) EV_THROW; /* update event loop time */

 #if EV_WALK_ENABLE

Changes appear to be part of this commit:
https://github.com/phusion/passenger/commit/a84b6ae1a64d2ae552d3e03c69d295a166200cd0#diff-8644f07c5dc22ffd1d2cae715cbbae56

	throw RuntimeException("Cannot create an event loop");
 	}

+	P_LOG_FILE_DESCRIPTOR_OPEN2(ev_backend_fd(loop), "libev event loop: backend
FD");
+
 	async = (ev_async *) malloc(sizeof(ev_async));
 	async->data = this;
 	ev_async_init(async, signalBackgroundEventLoopExit);
 	ev_async_start(loop, async);
+	P_LOG_FILE_DESCRIPTOR_OPEN2(ev_loop_get_pipe(loop, 0), "libev event loop:
async pipe 0");
+	P_LOG_FILE_DESCRIPTOR_OPEN2(ev_loop_get_pipe(loop, 1), "libev event loop:
async pipe 1");
 	safe = boost::make_shared<SafeLibev>(loop);
 	priv = new BackgroundEventLoopPrivate();
priv->thr = NULL;

~SafeLibev() {
 		destroy();
+		P_LOG_FILE_DESCRIPTOR_CLOSE(ev_loop_get_pipe(loop, 0));
+		P_LOG_FILE_DESCRIPTOR_CLOSE(ev_loop_get_pipe(loop, 1));
+		P_LOG_FILE_DESCRIPTOR_CLOSE(ev_backend_fd(loop));
 		ev_loop_destroy(loop);
}

Which allows for some additional logging of fd opening/closing.  I know
nothing about the motivation for this change, but I'm wondering if this would
be accepted by libev?

Thanks for your time.

--

-- 
Orion Poplawski
Technical Manager                     303-415-9701 x222
NWRA, Boulder/CoRA Office             FAX: 303-415-9702
3380 Mitchell Lane                       orion <at> nwra.com
Boulder, CO 80301                   http://www.nwra.com

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Thilo Schulz | 17 Apr 19:48 2015
Picon

Suggestion for new watcher type: called immediately after execution of current watcher has finished

Hello,

the software I am currently writing is very modular - with functions in
modules being called directly from the event library, and with modules
having control over when they can be unloaded (this may happen when
a final closing event arrives, and the module then knows it's done and can
unload).
I can't simply make the module itself unload from the same call as
the event watcher, because this would of course ruin the callstack.
What I was missing for this case was a way to make libev execute something
immediately after the current watcher is done, even before other pending
watchers are executed.
Instead, I used a prepare watcher, which is close enough for me. (In my
case it doesn't really matter if pending watchers are executed first).

The prepare watcher has its own traps, as I laid out in my prior email.

--

-- 
Best regards,
Thilo Schulz

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Thilo Schulz | 17 Apr 19:46 2015
Picon

ev_prepare watcher awkwardness

Dear list, dear Mr. Lehmann, 

first I would like to thank you for this excellent piece of software.
I've been using it for quite some time.
In developing software using this event library, I've noticed a
few "nice to haves" that I'm going to lay out in this email and a next email
to this list.

It so happens in my software there is a a prepare watcher which may,
somewhere in the call tree, add another prepare watcher, that shall execute
before the process blocks for new events.
If memory serves correctly looking at libev code, as this new prepare watcher
has not been properly "collected" yet, it will only be executed _after_ the
upcoming select()/poll(). While this collect behaviour is sensible for
file descriptors, in the case of ev_prepare() watchers this is somewhat
counterintuitive.

I am currently working around this by always
also installing an idle watcher to make sure the program doesn't block for at
least one event loop iteration. But like I said, this solution is rather awkward.

I can have a look at it and try to write a patch if you're interested. Thought
I'd ask first.

--

-- 
Best regards,
Thilo Schulz

_______________________________________________
libev mailing list
libev <at> lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Gmane