Redis модуль RESTORE вызов команды - PullRequest
0 голосов
/ 25 мая 2018

Я хочу восстановить сериализованный ключ из файла в память Redis в модуле.

Вот код:

int Unarchive_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {

    if (argc != 2) {
        RedisModule_WrongArity(ctx);
    } else {

        RedisModuleString *keyName = argv[1];
        long long unarchiedKeys = 0;
        const char *filename = RedisModule_StringPtrLen(keyName, NULL);
        FILE *f = fopen(filename, "r");

        if (f != NULL && access(filename, F_OK) != -1) {

            struct stat info;

            if (stat(filename, &info) != 0) {

                RedisModule_ReplyWithError(ctx, "Error during file read");
            }

            size_t valueSize = info.st_size * sizeof(char);
            char *keyValue = RedisModule_Alloc(valueSize);
            fread(&keyValue, (size_t) info.st_size, 1, f);
            fclose(f);
            RedisModule_ReplyWithCallReply(ctx, RedisModule_Call(ctx, "RESTORE", "slbc", keyName, 0, keyValue, "REPLACE"));

            remove(filename);
            unarchiedKeys++;
        }

        RedisModule_ReplyWithLongLong(ctx, unarchiedKeys);
    }
    return REDISMODULE_OK;
}

Когда я запускаю эту команду, я получаю SIGSEGV (Segmentation fault) при выполнении строки RedisModule_ReplyWithCallReply(ctx, RedisModule_Call(ctx, "RESTORE", "slcc", keyName, 0, keyValue, "REPLACE"));

Может кто-нибудь помочь мне решить эту проблему?

Заранее спасибо.

1 Ответ

0 голосов
/ 25 мая 2018

Ошибки сегмента часто вызваны удалением ссылки на нулевой указатель, который, в свою очередь, обычно указывает на адрес, который не является частью адресного пространства процесса.Хорошая ставка, что что-то в этом роде - ваша проблема.Как правило, кажется, что вы проделали довольно хорошую работу по проверке переменных перед их использованием, с несколькими заметными исключениями:

  • При первом использовании ctx (если только счет argc неверенили stat! = 0) находится в вызове RedisModule_ReplyWithCallReply.Следует проверить, что он не равен нулю перед использованием.
  • Возвращаемое значение RedisModule_Call не может быть проверено, когда оно вызывается в качестве аргумента для другой функции.И согласно этой документации API эта функция возвращает NULL для неправильного типа ответа.

Предложить удалить встроенный вызов для RedisModule_Call, чтобы вы могли проверить его возвращаемое значение, прежде чем передать его в качестве аргумента RedisModule_ReplyWithCallReply().

RedisModuleCallReply *reply = RedisModule_Call(ctx, "RESTORE", "slbc", keyName, 0, keyValue, valueSize, "REPLACE");
if(!reply)
{
   // handle error;
}
else
{
    RedisModule_ReplyWithCallReply(ctx, reply);
}

Редактировать:
Еще одна мысль, строка:

    fread(&keyValue, (size_t) info.st_size, 1, f);
          ^//not needed

Должно быть:

    fread(keyValue, (size_t) info.st_size, 1, f);
...