1. 20 Jan, 2022 2 commits
    • perryitay's avatar
      Adding module api for processing commands during busy jobs and allow flagging... · c4b78823
      perryitay authored
      
      Adding module api for processing commands during busy jobs and allow flagging the commands that should be handled at this status (#9963)
      
      Some modules might perform a long-running logic in different stages of Redis lifetime, for example:
      * command execution
      * RDB loading
      * thread safe context
      
      During this long-running logic Redis is not responsive.
      
      This PR offers 
      1. An API to process events while a busy command is running (`RM_Yield`)
      2. A new flag (`ALLOW_BUSY`) to mark the commands that should be handled during busy
        jobs which can also be used by modules (`allow-busy`)
      3. In slow commands and thread safe contexts, this flag will start rejecting commands with -BUSY only
        after `busy-reply-threshold`
      4. During loading (`rdb_load` callback), it'll process events right away (not wait for `busy-reply-threshold`),
        but either way, the processing is throttled to the server hz rate.
      5. Allow modules to Yield to redis background tasks, but not to client commands
      
      * rename `script-time-limit` to `busy-reply-threshold` (an alias to the pre-7.0 `lua-time-limit`)
      Co-authored-by: default avatarOran Agra <oran@redislabs.com>
      c4b78823
    • Madelyn Olson's avatar
      Fix double key declaration for renamenx and change flag to INSERT (#10137) · 22172a4a
      Madelyn Olson authored
      * Fix double key declaration for renamenx
      * Change the flag from UPDATE to INSERT, since it can not affect the data in the key
      22172a4a
  2. 19 Jan, 2022 6 commits
  3. 18 Jan, 2022 5 commits
    • Oran Agra's avatar
      New detailed key-spec flags (RO, RW, OW, RM, ACCESS, UPDATE, INSERT, DELETE) (#10122) · eef9c6b0
      Oran Agra authored
      The new ACL key based permissions in #9974 require the key-specs (#8324) to have more
      explicit flags rather than just READ and WRITE. See discussion in #10040
      
      This PR defines two groups of flags:
      One about how redis internally handles the key (mutually-exclusive).
      The other is about the logical operation done from the user's point of view (3 mutually exclusive
      write flags, and one read flag, all optional).
      In both groups, if we can't explicitly flag something as explicit read-only, delete-only, or
      insert-only, we flag it as `RW` or `UPDATE`.
      here's the definition from the code:
      ```
      /* Key-spec flags *
       * -------------- */
      /* The following refer what the command actually does with the value or metadata
       * of the key, and not necessarily the user data or how it affects it.
       * Each key-spec may must have exaclty one of these. Any operation that's not
       * distinctly deletion, overwrite or read-only would be marked as RW. */
      #define CMD_KEY_RO (1ULL<<0)     /* Read-Only - Reads the value of the key, but
                                        * doesn't necessarily returns it. */
      #define CMD_KEY_RW (1ULL<<1)     /* Read-Write - Modifies the data stored in the
                                        * value of the key or its metadata. */
      #define CMD_KEY_OW (1ULL<<2)     /* Overwrite - Overwrites the data stored in
                                        * the value of the key. */
      #define CMD_KEY_RM (1ULL<<3)     /* Deletes the key. */
      /* The follwing refer to user data inside the value of the key, not the metadata
       * like LRU, type, cardinality. It refers to the logical operation on the user's
       * data (actual input strings / TTL), being used / returned / copied / changed,
       * It doesn't refer to modification or returning of metadata (like type, count,
       * presence of data). Any write that's not INSERT or DELETE, would be an UPADTE.
       * Each key-spec may have one of the writes with or without access, or none: */
      #define CMD_KEY_ACCESS (1ULL<<4) /* Returns, copies or uses the user data from
                                        * the value of the key. */
      #define CMD_KEY_UPDATE (1ULL<<5) /* Updates data to the value, new value may
                                        * depend on the old value. */
      #define CMD_KEY_INSERT (1ULL<<6) /* Adds data to the value with no chance of,
                                        * modification or deletion of existing data. */
      #define CMD_KEY_DELETE (1ULL<<7) /* Explicitly deletes some content
                                        * from the value of the key. */
      ```
      
      Unrelated changes:
      - generate-command-code.py is only compatible with python3 (modified the shabang)
      - generate-command-code.py print file on json parsing error
      - rename `shard_channel` key-spec flag to just `channel`.
      - add INCOMPLETE flag in input spec of SORT and SORT_RO
      eef9c6b0
    • Wang Yuan's avatar
      Use const char pointer in redismodule.h as far as possible (#10064) · d697daa7
      Wang Yuan authored
      When I used C++ to develop a redis module. i  used `string.data()` as the second parameter `ele`
      of  `RedisModule_DigestAddStringBuffer`, but there is a warning, since we never change the `ele`,
      i think we should use `const char` for it.
      
      This PR adds const to just a handful of module APIs that required it, all not very widely used.
      The implication is a breaking change in terms of compilation error that's easy to resolve, and no ABI impact.
      The affected APIs are around Digest, Info injection, and Cluster bus messages.
      d697daa7
    • Ozan Tezcan's avatar
      Add event loop support to the module API (#10001) · 99ab4236
      Ozan Tezcan authored
      Modules can now register sockets/pipe to the Redis main thread event loop and do network operations asynchronously. Previously, modules had to maintain an event loop and another thread for asynchronous network operations.
      
      Also, if a module is calling API functions after doing some network operations, it had to synchronize its event loop thread's access with Redis main thread by locking the GIL, causing contention on the lock. After this commit, no synchronization is needed as module can operate in Redis main thread context. So, this commit may improve the performance for some use cases.
      
      Added three functions to the module API:
      
      * RedisModule_EventLoopAdd(int fd, int mask, RedisModuleEventLoopFunc func, void *user_data)
      * RedisModule_EventLoopDel(int fd, int mask)
      * RedisModule_EventLoopAddOneShot(RedisModuleEventLoopOneShotFunc func, void *user_data) - This function can be called from other threads to trigger callback on Redis main thread. Callback will be triggered only once. If Redis main thread is sleeping, this call will wake up the Redis main thread.
      Event loop callbacks are called by Redis main thread after locking the GIL. Inside callbacks, modules can operate as if they are holding the GIL.
      
      Added REDISMODULE_EVENT_EVENTLOOP event with two subevents:
      
      * REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP
      * REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP
      
      These events are for modules that want to participate in the before and after sleep action. e.g It might be useful to implement batching : Read data from the network, write all to a file in one go on BEFORE_SLEEP event.
      99ab4236
    • Yossi Gottlieb's avatar
      Fix additional AOF filename issues. (#10110) · 25e6d4d4
      Yossi Gottlieb authored
      This extends the previous fix (#10049) to address any form of
      non-printable or whitespace character (including newlines, quotes,
      non-printables, etc.)
      
      Also, removes the limitation on appenddirname, to align with the way
      filenames are handled elsewhere in Redis.
      25e6d4d4
    • Meir Shpilraien (Spielrein)'s avatar
      Fix `FUNCTION LOAD` ignores unknown parameter. (#10131) · 51f9bed3
      Meir Shpilraien (Spielrein) authored
      Following discussion on: https://github.com/redis/redis/issues/9899#issuecomment-1014689385
      Raise error if unknows parameter is given to `FUNCTION LOAD`.
      
      Before the fix:
      ```
      127.0.0.1:6379> function load LUA lib2 foo bar "local function test1() return 5 end redis.register_function('test1', test1)"
      OK
      ```
      
      After the fix:
      ```
      127.0.0.1:6379> function load LUA lib2 foo bar "local function test1() return 5 end redis.register_function('test1', test1)"
      (error) ERR Unkowns option given: foo
      ```
      51f9bed3
  4. 17 Jan, 2022 4 commits
    • Oran Agra's avatar
      Set repl-diskless-sync to yes by default, add repl-diskless-sync-max-replicas (#10092) · ae899589
      Oran Agra authored
      1. enable diskless replication by default
      2. add a new config named repl-diskless-sync-max-replicas that enables
         replication to start before the full repl-diskless-sync-delay was
         reached.
      3. put replica online sooner on the master (see below)
      4. test suite uses repl-diskless-sync-delay of 0 to be faster
      5. a few tests that use multiple replica on a pre-populated master, are
         now using the new repl-diskless-sync-max-replicas
      6. fix possible timing issues in a few cluster tests (see below)
      
      put replica online sooner on the master 
      ----------------------------------------------------
      there were two tests that failed because they needed for the master to
      realize that the replica is online, but the test code was actually only
      waiting for the replica to realize it's online, and in diskless it could
      have been before the master realized it.
      
      changes include two things:
      1. the tests wait on the right thing
      2. issues in the master, putting the replica online in two steps.
      
      the master used to put the replica as online in 2 steps. the first
      step was to mark it as online, and the second step was to enable the
      write event (only after getting ACK), but in fact the first step didn't
      contains some of the tasks to put it online (like updating good slave
      count, and sending the module event). this meant that if a test was
      waiting to see that the replica is online form the point of view of the
      master, and then confirm that the module got an event, or that the
      master has enough good replicas, it could fail due to timing issues.
      
      so now the full effect of putting the replica online, happens at once,
      and only the part about enabling the writes is delayed till the ACK.
      
      fix cluster tests 
      --------------------
      I added some code to wait for the replica to sync and avoid race
      conditions.
      later realized the sentinel and cluster tests where using the original 5
      seconds delay, so changed it to 0.
      
      this means the other changes are probably not needed, but i suppose
      they're still better (avoid race conditions)
      ae899589
    • zhaozhao.zz's avatar
      show subcommands latencystats (#10103) · 90916f16
      zhaozhao.zz authored
      
      
      since `info commandstats` already shows sub-commands, we should do the same in `info latencystats`.
      similarly, the LATENCY HISTOGRAM command now shows sub-commands (with their full name) when:
      * asking for all commands
      * asking for a specific container command
      * asking for a specific sub-command)
      Co-authored-by: default avatarOran Agra <oran@redislabs.com>
      90916f16
    • Binbin's avatar
      Fix timing issue in PSETEX/PEXPIRE sub-second expire tests (#10121) · 26ef5132
      Binbin authored
      These two tests have a high probability of failure
      on MacOS. Or it takes many retries to succeed.
      Keys often expire before we can access them.
      
      So this time we try to avoid this by reducing the time
      of the first `after`, or removeing the first `after`.
      
      The results of doing `20/81` and `0/101` are:
      - PEXPIRE (20/81): 1069/1949
      - PEXPIREAT (20/81): 1093/1949
      
      - PEXPIRE (0/101): 31936 / 31936
      - PEXPIREAT (0/101): 31936 / 31936
      
      The first number is the number of times that the
      test succeeded without any retries.
      The second number is the total number of executions.
      
      And we can see that `0/101` doesn't even need an extra
      retries. Also reduces the time required for testing.
      So in the end we chose `0/100`, i.e. remove the first `after`.
      
      As for `PEXPIREAT`, there is no failure, but we still changed
      it together, using `0/201`, after 2W tests, none of them failed.
      26ef5132
    • chenyang8094's avatar
      Use am instead of using server.aof_manifest directly to call... · d7aeb2ce
      chenyang8094 authored
      Use am instead of using server.aof_manifest directly to call getBaseAndIncrAppendOnlyFilesSize (#10123)
      
      d7aeb2ce
  5. 16 Jan, 2022 2 commits
    • David CARLIER's avatar
      zmalloc_get_rss netbsd impl fix proposal. (#10116) · 50fa627b
      David CARLIER authored
      Seems like the previous implementation was broken (always returning 0)
      
      since kinfo_proc2 is used the KERN_PROC2 sysctl oid is more appropriate
      and also the query's length was not necessarily accurate (6 here).
      50fa627b
    • sundb's avatar
      Fix quicklist node not being recompressed correctly after inserting a new node... · 32e7b46a
      sundb authored
      Fix quicklist node not being recompressed correctly after inserting a new node before or after it (#10120)
      
      ### Describe
      Fix crash found by CI, Introduced by #9849.
      When we do any operation on the quicklist, we should make sure that all nodes
      of the quicklist should not be in the recompressed state.
      
      ### Issues
      This PR fixes two issues with incorrect recompression.
      1. The current quicklist node is full and the previous node isn't full,
          the current node is not recompressed correctly after inserting elements into the previous node.
      2. The current quicklist node is full and the next node isn't full,
          the current node is not recompressed correctly after inserting elements into the next node.
      
      ### Test
      Add two tests to cover incorrect compression issues.
      
      ### Other
      Fix unittest test failure caused by assertion introduced by #9849.
      32e7b46a
  6. 15 Jan, 2022 3 commits
  7. 14 Jan, 2022 2 commits
    • Meir Shpilraien (Spielrein)'s avatar
      Function Flags support (no-writes, no-cluster, allow-state, allow-oom) (#10066) · 4db4b434
      Meir Shpilraien (Spielrein) authored
      # Redis Functions Flags
      
      Following the discussion on #10025 Added Functions Flags support.
      The PR is divided to 2 sections:
      * Add named argument support to `redis.register_function` API.
      * Add support for function flags
      
      ## `redis.register_function` named argument support
      
      The first part of the PR adds support for named argument on `redis.register_function`, example:
      ```
      redis.register_function{
          function_name='f1',
          callback=function()
              return 'hello'
          end,
          description='some desc'
      }
      ```
      
      The positional arguments is also kept, which means that it still possible to write:
      ```
      redis.register_function('f1', function() return 'hello' end)
      ```
      
      But notice that it is no longer possible to pass the optional description argument on the positional
      argument version. Positional argument was change to allow passing only the mandatory arguments
      (function name and callback). To pass more arguments the user must use the named argument version.
      
      As with positional arguments, the `function_name` and `callback` is mandatory and an error will be
      raise if those are missing. Also, an error will be raise if an unknown argument name is given or the
      arguments type is wrong.
      
      Tests was added to verify the new syntax.
      
      ## Functions Flags
      
      The second part of the PR is adding functions flags support.
      Flags are given to Redis when the engine calls `functionLibCreateFunction`, supported flags are:
      
      * `no-writes` - indicating the function perform no writes which means that it is OK to run it on:
         * read-only replica
         * Using FCALL_RO
         * If disk error detected
         
         It will not be possible to run a function in those situations unless the function turns on the `no-writes` flag
      
      * `allow-oom` - indicate that its OK to run the function even if Redis is in OOM state, if the function will
        not turn on this flag it will not be possible to run it if OOM reached (even if the function declares `no-writes`
        and even if `fcall_ro` is used). If this flag is set, any command will be allow on OOM (even those that is
        marked with CMD_DENYOOM). The assumption is that this flag is for advance users that knows its
        meaning and understand what they are doing, and Redis trust them to not increase the memory usage.
        (e.g. it could be an INCR or a modification on an existing key, or a DEL command)
      
      * `allow-state` - indicate that its OK to run the function on stale replica, in this case we will also make
        sure the function is only perform `stale` commands and raise an error if not.
      
      * `no-cluster` - indicate to disallow running the function if cluster is enabled.
      
      Default behaviure of functions (if no flags is given):
      1. Allow functions to read and write
      2. Do not run functions on OOM
      3. Do not run functions on stale replica
      4. Allow functions on cluster
      
      ### Lua API for functions flags
      
      On Lua engine, it is possible to give functions flags as `flags` named argument:
      
      ```
      redis.register_function{function_name='f1', callback=function() return 1 end, flags={'no-writes', 'allow-oom'}, description='description'}
      ```
      
      The function flags argument must be a Lua table that contains all the requested flags, The following
      will result in an error:
      * Unknown flag
      * Wrong flag type
      
      Default behaviour is the same as if no flags are used.
      
      Tests were added to verify all flags functionality
      
      ## Additional changes
      * mark FCALL and FCALL_RO with CMD_STALE flag (unlike EVAL), so that they can run if the function was
        registered with the `allow-stale` flag.
      * Verify `CMD_STALE` on `scriptCall` (`redis.call`), so it will not be possible to call commands from script while
        stale unless the command is marked with the `CMD_STALE` flags. so that even if the function is allowed while
        stale we do not allow it to bypass the `CMD_STALE` flag of commands.
      * Flags section was added to `FUNCTION LIST` command to provide the set of flags for each function:
      ```
      > FUNCTION list withcode
      1)  1) "library_name"
          2) "test"
          3) "engine"
          4) "LUA"
          5) "description"
          6) (nil)
          7) "functions"
          8) 1) 1) "name"
                2) "f1"
                3) "description"
                4) (nil)
                5) "flags"
                6) (empty array)
          9) "library_code"
         10) "redis.register_function{function_name='f1', callback=function() return 1 end}"
      ```
      * Added API to get Redis version from within a script, The redis version can be provided using:
         1. `redis.REDIS_VERSION` - string representation of the redis version in the format of MAJOR.MINOR.PATH
         2. `redis.REDIS_VERSION_NUM` - number representation of the redis version in the format of `0x00MMmmpp`
            (`MM` - major, `mm` - minor,  `pp` - patch). The number version can be used to check if version is greater or less 
            another version. The string version can be used to return to the user or print as logs.
      
         This new API is provided to eval scripts and functions, it also possible to use this API during functions loading phase.
      4db4b434
    • Peter Hickey's avatar
      Fix typo in deps/README.md (#10113) · 38a51167
      Peter Hickey authored
      38a51167
  8. 13 Jan, 2022 3 commits
    • Binbin's avatar
      Fix kill aof rewrite child test (#10107) · 56a80205
      Binbin authored
      The dbs doesn't have any keys, `rdb-key-save-delay`
      config has no effect that cause the rewrite to complete.
      
      It was introduced in #10015.
      56a80205
    • Ozan Tezcan's avatar
      Added RM_MonotonicMicroseconds() API to provide monotonic time function (#10101) · f41cc870
      Ozan Tezcan authored
      Added RM_MonotonicMicroseconds(). Modules can use monotonic timestamp counter for measurements.
      f41cc870
    • chenyang8094's avatar
      Always create base AOF file when redis start from empty. (#10102) · e9bff797
      chenyang8094 authored
      
      
      Force create a BASE file (use a foreground `rewriteAppendOnlyFile`) when redis starts from an
      empty data set and  `appendonly` is  yes.
      
      The reasoning is that normally, after redis is running for some time, and the AOF has gone though
      a few rewrites, there's always a base rdb file. and the scenario where the base file is missing, is
      kinda rare (happens only at empty startup), so this change normalizes it.
      But more importantly, there are or could be some complex modules that are started with some
      configuration, when they create persistence they write that configuration to RDB AUX fields, so
      that can can always know with which configuration the persistence file they're loading was
      created (could be critical). there is (was) one scenario in which they could load their persisted data,
      and that configuration was missing, and this change fixes it.
      
      Add a new module event: REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START, similar to
      REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START which is async.
      Co-authored-by: default avatarOran Agra <oran@redislabs.com>
      e9bff797
  9. 12 Jan, 2022 1 commit
    • Binbin's avatar
      Show subcommand full name in error log / ACL LOG (#10105) · 20c33fe6
      Binbin authored
      Use `getFullCommandName` to get the full name of the command.
      It can also get the full name of the subcommand, like "script|help".
      
      Before:
      ```
      > SCRIPT HELP
      (error) NOPERM this user has no permissions to run the 'help' command or its subcommand
      
      > ACL LOG
          7) "object"
          8) "help"
      ```
      
      After:
      ```
      > SCRIPT HELP
      (error) NOPERM this user has no permissions to run the 'script|help' command
      
      > ACL LOG
          7) "object"
          8) "script|help"
      ```
      
      Fix #10094
      20c33fe6
  10. 11 Jan, 2022 7 commits
    • Binbin's avatar
      Add script tests to cover keys with expiration time set (#10096) · e22146b0
      Binbin authored
      This commit adds some tests that the test cases will
      access the keys with expiration time set in the script call.
      There was no test case for this part before. See #10080
      
      Also there is a test will cover #1525. we block the time so
      that the key can not expire in the middle of the script execution.
      
      Other changes:
      1. Delete `evalTimeSnapshot` and just use `scriptTimeSnapshot` in it's place.
      2. Some cleanups to scripting.tcl.
      3. better names for tests that run in a loop to make them distinctable 
      e22146b0
    • Ozan Tezcan's avatar
      Reuse temporary client objects for blocked clients by module (#9940) · 6790d848
      Ozan Tezcan authored
      Added a pool for temporary client objects to reuse in module operations.
      By reusing temporary clients, we are avoiding expensive createClient()/freeClient()
      calls and improving performance of RM_BlockClient() and  RM_GetThreadSafeContext() calls. 
      
      This commit contains two optimizations: 
      
      1 - RM_BlockClient() and RM_GetThreadSafeContext() calls create temporary clients and they are freed in
      RM_UnblockClient() and RM_FreeThreadSafeContext() calls respectively. Creating/destroying client object
      takes quite time. To avoid that, added a pool of temporary clients. Pool expands when more clients are needed.
      Also, added a cron function to shrink the pool and free unused clients after some time. Pool starts with zero
      clients in it. It does not have max size and can grow unbounded as we need it. We will keep minimum of 8
      temporary clients in the pool once created. Keeping small amount of clients to avoid client allocation costs
      if temporary clients are required after some idle period.
      
      2 - After unblocking a client (RM_UnblockClient()), one byte is written to pipe to wake up Redis main thread.
      If there are many clients that will be unblocked, each operation requires one write() call which is quite expensive.
      Changed code to avoid subsequent calls if possible. 
      
      There are a few more places that need temporary client objects (e.g RM_Call()). These are now using the same
      temporary client pool to make things more centralized. 
      6790d848
    • Oran Agra's avatar
      Move doc metadata from COMMAND to COMMAND DOCS (#10056) · 3204a035
      Oran Agra authored
      Syntax:
      `COMMAND DOCS [<command name> ...]`
      
      Background:
      Apparently old version of hiredis (and thus also redis-cli) can't
      support more than 7 levels of multi-bulk nesting.
      
      The solution is to move all the doc related metadata from COMMAND to a
      new COMMAND DOCS sub-command.
      
      The new DOCS sub-command returns a map of commands (not an array like in COMMAND),
      And the same goes for the `subcommands` field inside it (also contains a map)
      
      Besides that, the remaining new fields of COMMAND (hints, key-specs, and
      sub-commands), are placed in the outer array rather than a nested map.
      this was done mainly for consistency with the old format.
      
      Other changes:
      ---
      * Allow COMMAND INFO with no arguments, which returns all commands, so that we can some day deprecated
        the plain COMMAND (no args)
      
      * Reduce the amount of deferred replies from both COMMAND and COMMAND
        DOCS, especially in the inner loops, since these create many small
        reply objects, which lead to many small write syscalls and many small
        TCP packets.
        To make this easier, when populating the command table, we count the
        history, args, and hints so we later know their size in advance.
        Additionally, the movablekeys flag was moved into the flags register.
      * Update generate-commands-json.py to take the data from both command, it
        now executes redis-cli directly, instead of taking input from stdin.
      * Sub-commands in both COMMAND (and COMMAND INFO), and also COMMAND DOCS,
        show their full name. i.e. CONFIG 
      *   GET will be shown as `config|get` rather than just `get`.
        This will be visible both when asking for `COMMAND INFO config` and COMMAND INFO config|get`, but is
        especially important for the later.
        i.e. imagine someone doing `COMMAND INFO slowlog|get config|get` not being able to distinguish between the two
        items in the array response.
      3204a035
    • guybe7's avatar
      Module events: Fail RM_SubscribeToServerEvent if event is too new (#9987) · 5009b43d
      guybe7 authored
      We must fail RM_SubscribeToServerEvent in case a module, that
      was compiled with a new redismodule.h, tries to subscribe to an
      event that doesn't exist on an old redis-server
      5009b43d
    • Binbin's avatar
      LPOP/RPOP with count against non existing list return null array (#10095) · 39feee8e
      Binbin authored
      It used to return `$-1` in RESP2, now we will return `*-1`.
      This is a bug in redis 6.2 when COUNT was added, the `COUNT`
      option was introduced in #8179. Fix #10089.
      
      the documentation of [LPOP](https://redis.io/commands/lpop) says
      ```
      When called without the count argument:
      Bulk string reply: the value of the first element, or nil when key does not exist.
      
      When called with the count argument:
      Array reply: list of popped elements, or nil when key does not exist.
      ```
      39feee8e
    • 小令童鞋's avatar
      fix redis crached by using eval with access to volatile keys (#10080) · 1e25bdf7
      小令童鞋 authored
      This is a recent regression from the Redis Functions commits
      1e25bdf7
    • Madelyn Olson's avatar
      d0949b7c
  11. 10 Jan, 2022 4 commits
  12. 09 Jan, 2022 1 commit
    • Binbin's avatar
      Fix crash when error [sub]command name contains | (#10082) · a84c964d
      Binbin authored
      The following error commands will crash redis-server:
      ```
      > get|
      Error: Server closed the connection
      > get|set
      Error: Server closed the connection
      > get|other
      ```
      
      The reason is in #9504, we use `lookupCommandBySds` for find the
      container command. And it split the command (argv[0]) with `|`.
      If we input something like `get|other`, after the split, `get`
      will become a valid command name, pass the `ERR unknown command`
      check, and finally crash in `addReplySubcommandSyntaxError`
      
      In this case we do not need to split the command name with `|`
      and just look in the commands dict to find if `argv[0]` is a
      container command.
      
      So this commit introduce a new function call `isContainerCommandBySds`
      that it will return true if a command name is a container command.
      
      Also with the old code, there is a incorrect error message:
      ```
      > config|get set
      (error) ERR Unknown subcommand or wrong number of arguments for 'set'. Try CONFIG|GET HELP.
      ```
      
      The crash was reported in #10070.
      a84c964d