1. 27 Aug, 2020 1 commit
    • Oran Agra's avatar
      Fix rejectCommand trims newline in shared error objects, hung clients (#7714) · 9fcd9e19
      Oran Agra authored
      65a3307b
      
       (released in 6.0.6) has a side effect, when processCommand
      rejects a command with pre-made shared object error string, it trims the
      newlines from the end of the string. if that string is later used with
      addReply, the newline will be missing, breaking the protocol, and
      leaving the client hung.
      
      It seems that the only scenario which this happens is when replying with
      -LOADING to some command, and later using that reply from the CONFIG
      SET command (still during loading). this will result in hung client.
      
      Refactoring the code in order to avoid trimming these newlines from
      shared string objects, and do the newline trimming only in other cases
      where it's needed.
      Co-authored-by: default avatarGuy Benoish <guy.benoish@redislabs.com>
      9fcd9e19
  2. 23 Jun, 2020 1 commit
    • Oran Agra's avatar
      EXEC always fails with EXECABORT and multi-state is cleared · 65a3307b
      Oran Agra authored
      In order to support the use of multi-exec in pipeline, it is important that
      MULTI and EXEC are never rejected and it is easy for the client to know if the
      connection is still in multi state.
      
      It was easy to make sure MULTI and DISCARD never fail (done by previous
      commits) since these only change the client state and don't do any actual
      change in the server, but EXEC is a different story.
      
      Since in the past, it was possible for clients to handle some EXEC errors and
      retry the EXEC, we now can't affort to return any error on EXEC other than
      EXECABORT, which now carries with it the real reason for the abort too.
      
      Other fixes in this commit:
      - Some checks that where performed at the time of queuing need to be re-
        validated when EXEC runs, for instance if the transaction contains writes
        commands, it needs to be aborted. there was one check that was already done
        in execCommand (-READONLY), but other checks where missing: -OOM, -MISCONF,
        -NOREPLICAS, -MASTERDOWN
      - When a command is rejected by processCommand it was rejected with addReply,
        which was not recognized as an error in case the bad command came from the
        master. this will enable to count or MONITOR these errors in the future.
      - make it easier for tests to create additional (non deferred) clients.
      - add tests for the fixes of this commit.
      65a3307b
  3. 09 Jun, 2020 1 commit
  4. 08 Jun, 2020 1 commit
  5. 05 May, 2020 1 commit
  6. 04 Feb, 2020 1 commit
  7. 30 Jan, 2020 1 commit
  8. 27 Jan, 2020 1 commit
  9. 22 Nov, 2019 1 commit
  10. 11 Sep, 2019 1 commit
  11. 09 Jan, 2019 3 commits
  12. 11 Dec, 2018 3 commits
  13. 03 Aug, 2018 1 commit
  14. 12 Jul, 2017 1 commit
    • antirez's avatar
      Fix replication of SLAVEOF inside transaction. · e74f0aa6
      antirez authored
      In Redis 4.0 replication, with the introduction of PSYNC2, masters and
      slaves replicate commands to cascading slaves and to the replication
      backlog itself in a different way compared to the past.
      
      Masters actually replicate the effects of client commands.
      Slaves just propagate what they receive from masters.
      
      This mechanism can cause problems when the configuration of an instance
      is changed from master to slave inside a transaction. For instance
      we could send to a master instance the following sequence:
      
          MULTI
          SLAVEOF 127.0.0.1 0
          EXEC
          SLAVEOF NO ONE
      
      Before the fixes in this commit, the MULTI command used to be propagated
      into the replication backlog, however after the SLAVEOF command the
      instance is a slave, so the EXEC implementation failed to also propagate
      the EXEC command. When the slaves of the above instance reconnected,
      they were incrementally synchronized just sending a "MULTI". This put
      the master client (in the slaves) into MULTI state, breaking the
      replication.
      
      Notably even Redis Sentinel uses the above approach in order to guarantee
      that configuration changes are always performed together with rewrites
      of the configuration and with clients disconnection. Sentiel does:
      
          MULTI
          SLAVEOF ...
          CONFIG REWRITE
          CLIENT KILL TYPE normal
          EXEC
      
      So this was a really problematic issue. However even with the fix in
      this commit, that will add the final EXEC to the replication stream in
      case the instance was switched from master to slave during the
      transaction, the result would be to increment the slave replication
      offset, so a successive reconnection with the new master, will not
      permit a successful partial resynchronization: no way the new master can
      provide us with the backlog needed, we incremented our offset to a value
      that the new master cannot have.
      
      However the EXEC implementation waits to emit the MULTI, so that if the
      commands inside the transaction actually do not need to be replicated,
      no commands propagation happens at all. From multi.c:
      
          if (!must_propagate && !(c->cmd->flags & (CMD_READONLY|CMD_ADMIN))) {
      	execCommandPropagateMulti(c);
      	must_propagate = 1;
          }
      
      The above code is already modified by this commit you are reading.
      Now also ADMIN commands do not trigger the emission of MULTI. It is actually
      not clear why we do not just check for CMD_WRITE... Probably I wrote it this
      way in order to make the code more reliable: better to over-emit MULTI
      than not emitting it in time.
      
      So this commit should indeed fix issue #3836 (verified), however it looks
      like some reconsideration of this code path is needed in the long term.
      
      BONUS POINT: The reverse bug.
      
      Even in a read only slave "B", in a replication setup like:
      
      	A -> B -> C
      
      There are commands without the READONLY nor the ADMIN flag, that are also
      not flagged as WRITE commands. An example is just the PING command.
      
      So if we send B the following sequence:
      
          MULTI
          PING
          SLAVEOF NO ONE
          EXEC
      
      The result will be the reverse bug, where only EXEC is emitted, but not the
      previous MULTI. However this apparently does not create problems in practice
      but it is yet another acknowledge of the fact some work is needed here
      in order to make this code path less surprising.
      
      Note that there are many different approaches we could follow. For instance
      MULTI/EXEC blocks containing administrative commands may be allowed ONLY
      if all the commands are administrative ones, otherwise they could be
      denined. When allowed, the commands could simply never be replicated at all.
      e74f0aa6
  15. 27 Jul, 2015 1 commit
  16. 26 Jul, 2015 3 commits
  17. 08 Aug, 2014 1 commit
  18. 26 Jun, 2014 1 commit
  19. 26 Mar, 2013 3 commits
    • antirez's avatar
      Transactions: propagate MULTI/EXEC only when needed. · 71f3e743
      antirez authored
      MULTI/EXEC is now propagated to the AOF / Slaves only once we encounter
      the first command that is not a read-only one inside the transaction.
      
      The old behavior was to always propagate an empty MULTI/EXEC block when
      the transaction was composed just of read only commands, or even
      completely empty. This created two problems:
      
      1) It's a bandwidth waste in the replication link and a space waste
         inside the AOF file.
      
      2) We used to always increment server.dirty to force the propagation of
         the EXEC command, resulting into triggering RDB saves more often
         than needed.
      
      Note: even read-only commands may also trigger writes that will be
      propagated, when we access a key that is found expired and Redis will
      synthesize a DEL operation. However there is no need for this to stay
      inside the transaction itself, but only to be ordered.
      
      So for instance something like:
      
          MULTI
          GET foo
          SET key zap
          EXEC
      
      May be propagated into:
      
          DEL foo
          MULTI
          SET key zap
          EXEC
      
      While the DEL is outside the transaction, the commands are delivered in
      the right order and it is not possible for other commands to be inserted
      between DEL and MULTI.
      71f3e743
    • antirez's avatar
      02c269e2
    • antirez's avatar
      Transactions: use the propagate() API to propagate MULTI. · 2f497340
      antirez authored
      The behavior is the same, but the code is now cleaner and uses the
      proper interface instead of dealing directly with AOF/replication
      functions.
      2f497340
  20. 12 Feb, 2013 1 commit
  21. 19 Jan, 2013 1 commit
  22. 22 Nov, 2012 1 commit
    • antirez's avatar
      Safer handling of MULTI/EXEC on errors. · 3d139127
      antirez authored
      After the transcation starts with a MULIT, the previous behavior was to
      return an error on problems such as maxmemory limit reached. But still
      to execute the transaction with the subset of queued commands on EXEC.
      
      While it is true that the client was able to check for errors
      distinguish QUEUED by an error reply, MULTI/EXEC in most client
      implementations uses pipelining for speed, so all the commands and EXEC
      are sent without caring about replies.
      
      With this change:
      
      1) EXEC fails if at least one command was not queued because of an
      error. The EXECABORT error is used.
      2) A generic error is always reported on EXEC.
      3) The client DISCARDs the MULTI state after a failed EXEC, otherwise
      pipelining multiple transactions would be basically impossible:
      After a failed EXEC the next transaction would be simply queued as
      the tail of the previous transaction.
      3d139127
  23. 08 Nov, 2012 1 commit
  24. 16 Oct, 2012 1 commit
    • antirez's avatar
      Fix MULTI / EXEC rendering in MONITOR output. · a1b1c1ea
      antirez authored
      Before of this commit it used to be like this:
      
      MULTI
      EXEC
      ... actual commands of the transaction ...
      
      Because after all that is the natural order of things. Transaction
      commands are queued and executed *only after* EXEC is called.
      
      However this makes debugging with MONITOR a mess, so the code was
      modified to provide a coherent output.
      
      What happens is that MULTI is rendered in the MONITOR output as far as
      possible, instead EXEC is propagated only after the transaction is
      executed, or even in the case it fails because of WATCH, so in this case
      you'll simply see:
      
      MULTI
      EXEC
      
      An empty transaction.
      a1b1c1ea
  25. 20 Mar, 2012 1 commit
    • antirez's avatar
      Support for read-only slaves. Semantical fixes. · f3fd419f
      antirez authored
      This commit introduces support for read only slaves via redis.conf and CONFIG GET/SET commands. Also various semantical fixes are implemented here:
      
      1) MULTI/EXEC with only read commands now work where the server is into a state where writes (or commands increasing memory usage) are not allowed. Before this patch everything inside a transaction would fail in this conditions.
      
      2) Scripts just calling read-only commands will work against read only
      slaves, when the server is out of memory, or when persistence is into an
      error condition. Before the patch EVAL always failed in this condition.
      f3fd419f
  26. 02 Feb, 2012 1 commit
  27. 21 Dec, 2011 1 commit
  28. 25 Nov, 2011 1 commit
  29. 04 Oct, 2011 1 commit
  30. 08 Jul, 2011 1 commit
    • antirez's avatar
      Take a pointer to the relevant entry of the command table in the client... · 09e2d9ee
      antirez authored
      Take a pointer to the relevant entry of the command table in the client structure. This is generally a more sounding design, simplifies a few functions prototype, and as a side effect fixes a bug related to the conversion of EXPIRE -1 to DEL: before of this fix Redis tried to convert it into an EXPIREAT in the AOF code, regardless of our rewrite of the command.
      09e2d9ee
  31. 23 Feb, 2011 1 commit
  32. 03 Nov, 2010 1 commit