1. 14 May, 2020 1 commit
  2. 12 May, 2020 1 commit
  3. 15 Oct, 2019 1 commit
  4. 07 Oct, 2019 1 commit
    • Oran Agra's avatar
      diskless replication rdb transfer uses pipe, and writes to sockets form the parent process. · 5a477946
      Oran Agra authored
      misc:
      - handle SSL_has_pending by iterating though these in beforeSleep, and setting timeout of 0 to aeProcessEvents
      - fix issue with epoll signaling EPOLLHUP and EPOLLERR only to the write handlers. (needed to detect the rdb pipe was closed)
      - add key-load-delay config for testing
      - trim connShutdown which is no longer needed
      - rioFdsetWrite -> rioFdWrite - simplified since there's no longer need to write to multiple FDs
      - don't detect rdb child exited (don't call wait3) until we detect the pipe is closed
      - Cleanup bad optimization from rio.c, add another one
      5a477946
  5. 28 Mar, 2018 1 commit
    • antirez's avatar
      Fix ae.c when a timer finalizerProc adds an event. · 8ac7af1c
      antirez authored
      While this feature is not used by Redis, ae.c implements the ability for
      a timer to call a finalizer callback when an timer event is deleted.
      This feature was bugged since the start, and because it was never used
      we never noticed a problem. However Anthony LaTorre was using the same
      library in order to implement a different system: he found a bug that he
      describes as follows, and which he fixed with the patch in this commit,
      sent me by private email:
      
          --- Anthony email ---
      
      've found one bug in the current implementation of the timed events.
      It's possible to lose track of a timed event if an event is added in
      the finalizerProc of another event.
      
      For example, suppose you start off with three timed events 1, 2, and
      3. Then the linked list looks like:
      
      3 -> 2 -> 1
      
      Then, you run processTimeEvents and events 2 and 3 finish, so now the
      list looks like:
      
      -1 -> -1 -> 2
      
      Now, on the next iteration of processTimeEvents it starts by deleting
      the first event, and suppose this finalizerProc creates a new event,
      so that the list looks like this:
      
      4 -> -1 -> 2
      
      On the next iteration of the while loop, when it gets to the second
      event, the variable prev is still set to NULL, so that the head of the
      event loop after the next event will be set to 2, i.e. after deleting
      the next event the event loop will look like:
      
      2
      
      and the event with id 4 will be lost.
      
      I've attached an example program to illustrate the issue. If you run
      it you will see that it prints:
      
      ```
      foo id = 0
      spam!
      ```
      
      But if you uncomment line 29 and run it again it won't print "spam!".
      
          --- End of email ---
      
      Test.c source code is as follows:
      
          #include "ae.h"
          #include <stdio.h>
      
          aeEventLoop *el;
      
          int foo(struct aeEventLoop *el, long long id, void *data)
          {
      	printf("foo id = %lld\n", id);
      
      	return AE_NOMORE;
          }
      
          int spam(struct aeEventLoop *el, long long id, void *data)
          {
      	printf("spam!\n");
      
      	return AE_NOMORE;
          }
      
          void bar(struct aeEventLoop *el, void *data)
          {
      	aeCreateTimeEvent(el, 0, spam, NULL, NULL);
          }
      
          int main(int argc, char **argv)
          {
      	el = aeCreateEventLoop(100);
      
      	//aeCreateTimeEvent(el, 0, foo, NULL, NULL);
      	aeCreateTimeEvent(el, 0, foo, NULL, bar);
      
      	aeMain(el);
      
      	return 0;
          }
      
      Anthony fixed the problem by using a linked list for the list of timers, and
      sent me back this patch after he tested the code in production for some time.
      The code looks sane to me, so committing it to Redis.
      8ac7af1c
  6. 27 Feb, 2018 1 commit
    • antirez's avatar
      ae.c: introduce the concept of read->write barrier. · 548e478e
      antirez authored
      AOF fsync=always, and certain Redis Cluster bus operations, require to
      fsync data on disk before replying with an acknowledge.
      In such case, in order to implement Group Commits, we want to be sure
      that queries that are read in a given cycle of the event loop, are never
      served to clients in the same event loop iteration. This way, by using
      the event loop "before sleep" callback, we can fsync the information
      just one time before returning into the event loop for the next cycle.
      This is much more efficient compared to calling fsync() multiple times.
      
      Unfortunately because of a bug, this was not always guaranteed: the
      actual way the events are installed was the sole thing that could
      control. Normally this problem is hard to trigger when AOF is enabled
      with fsync=always, because we try to flush the output buffers to the
      socekt directly in the beforeSleep() function of Redis. However if the
      output buffers are full, we actually install a write event, and in such
      a case, this bug could happen.
      
      This change to ae.c modifies the event loop implementation to make this
      concept explicit. Write events that are registered with:
      
          AE_WRITABLE|AE_BARRIER
      
      Are guaranteed to never fire after the readable event was fired for the
      same file descriptor. In this way we are sure that data is persisted to
      disk before the client performing the operation receives an
      acknowledged.
      
      However note that this semantics does not provide all the guarantees
      that one may believe are automatically provided. Take the example of the
      blocking list operations in Redis.
      
      With AOF and fsync=always we could have:
      
          Client A doing: BLPOP myqueue 0
          Client B doing: RPUSH myqueue a b c
      
      In this scenario, Client A will get the "a" elements immediately after
      the Client B RPUSH will be executed, even before the operation is persisted.
      However when Client B will get the acknowledge, it can be sure that
      "b,c" are already safe on disk inside the list.
      
      What to note here is that it cannot be assumed that Client A receiving
      the element is a guaranteed that the operation succeeded from the point
      of view of Client B.
      
      This is due to the fact that the barrier exists within the same socket,
      and not between different sockets. However in the case above, the
      element "a" was not going to be persisted regardless, so it is a pretty
      synthetic argument.
      548e478e
  7. 10 Jul, 2017 1 commit
    • antirez's avatar
      Event loop: call after sleep() only from top level. · 54e4bbea
      antirez authored
      In general we do not want before/after sleep() callbacks to be called
      when we re-enter the event loop, since those calls are only designed in
      order to perform operations every main iteration of the event loop, and
      re-entering is often just a way to incrementally serve clietns with
      error messages or other auxiliary operations. However, if we call the
      callbacks, we are then forced to think at before/after sleep callbacks
      as re-entrant, which is much harder without any good need.
      
      However here there was also a clear bug: beforeSleep() was actually
      never called when re-entering the event loop. But the new afterSleep()
      callback was. This is broken and in this instance re-entering
      afterSleep() caused a modules GIL dead lock.
      54e4bbea
  8. 03 May, 2017 1 commit
  9. 04 Apr, 2016 1 commit
    • antirez's avatar
      Fix ae.c to avoid timers infinite loop. · 67b70a18
      antirez authored
      This fix was suggested by Anthony LaTorre, that provided also a good
      test case that was used to verify the fix.
      
      The problem with the old implementation is that, the time returned by
      a timer event (that is the time after it want to run again) is added
      to the event *start time*. So if the event takes, in order to run, more
      than the time it says it want to be scheduled again for running, an
      infinite loop is triggered.
      67b70a18
  10. 28 Jun, 2013 1 commit
  11. 08 Nov, 2012 1 commit
  12. 04 Oct, 2012 1 commit
    • Jokea's avatar
      Force expire all timer events when system clock skew is detected. · b7b2a1cc
      Jokea authored
      When system time changes back, the timer will not worker properly
      hence some core functionality of redis will stop working(e.g. replication,
      bgsave, etc). See issue #633 for details.
      
      The patch saves the previous time and when a system clock skew is detected,
      it will force expire all timers.
      
      Modiifed by @antirez: the previous time was moved into the eventLoop
      structure to make sure the library is still thread safe as long as you
      use different event loops into different threads (otherwise you need
      some synchronization). More comments added about the reasoning at the
      base of the patch, that's worth reporting here:
      
      /* If the system clock is moved to the future, and then set back to the
       * right value, time events may be delayed in a random way. Often this
       * means that scheduled operations will not be performed soon enough.
       *
       * Here we try to detect system clock skews, and force all the time
       * events to be processed ASAP when this happens: the idea is that
       * processing events earlier is less dangerous than delaying them
       * indefinitely, and practice suggests it is. */
      b7b2a1cc
  13. 15 Dec, 2011 1 commit
  14. 21 Nov, 2011 1 commit
  15. 01 Jul, 2010 1 commit
    • antirez's avatar
      redis.c split into many different C files. · e2641e09
      antirez authored
      networking related stuff moved into networking.c
      
      moved more code
      
      more work on layout of source code
      
      SDS instantaneuos memory saving. By Pieter and Salvatore at VMware ;)
      
      cleanly compiling again after the first split, now splitting it in more C files
      
      moving more things around... work in progress
      
      split replication code
      
      splitting more
      
      Sets split
      
      Hash split
      
      replication split
      
      even more splitting
      
      more splitting
      
      minor change
      e2641e09
  16. 19 Feb, 2010 1 commit
  17. 28 Jan, 2010 1 commit
  18. 20 Jan, 2010 1 commit
  19. 28 Nov, 2009 1 commit
  20. 23 Nov, 2009 1 commit
  21. 22 Mar, 2009 1 commit