Load a module and initialize it. On success C_OK is returned, otherwise * C_ERR is returned. */
| 8541 | /* Load a module and initialize it. On success C_OK is returned, otherwise |
| 8542 | * C_ERR is returned. */ |
| 8543 | int moduleLoad(const char *path, void **module_argv, int module_argc) { |
| 8544 | int (*onload)(void *, void **, int); |
| 8545 | void *handle; |
| 8546 | RedisModuleCtx ctx = REDISMODULE_CTX_INIT; |
| 8547 | ctx.client = moduleFreeContextReusedClient; |
| 8548 | selectDb(ctx.client, 0); |
| 8549 | |
| 8550 | struct stat st; |
| 8551 | if (stat(path, &st) == 0) |
| 8552 | { // this check is best effort |
| 8553 | if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { |
| 8554 | serverLog(LL_WARNING, "Module %s failed to load: It does not have execute permissions.", path); |
| 8555 | return C_ERR; |
| 8556 | } |
| 8557 | } |
| 8558 | |
| 8559 | handle = dlopen(path,RTLD_NOW|RTLD_LOCAL); |
| 8560 | if (handle == NULL) { |
| 8561 | serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror()); |
| 8562 | return C_ERR; |
| 8563 | } |
| 8564 | onload = (int (*)(void *, void **, int))(unsigned long) dlsym(handle,"RedisModule_OnLoad"); |
| 8565 | if (onload == NULL) { |
| 8566 | dlclose(handle); |
| 8567 | serverLog(LL_WARNING, |
| 8568 | "Module %s does not export RedisModule_OnLoad() " |
| 8569 | "symbol. Module not loaded.",path); |
| 8570 | return C_ERR; |
| 8571 | } |
| 8572 | if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) { |
| 8573 | if (ctx.module) { |
| 8574 | moduleUnregisterCommands(ctx.module); |
| 8575 | moduleUnregisterSharedAPI(ctx.module); |
| 8576 | moduleUnregisterUsedAPI(ctx.module); |
| 8577 | moduleFreeModuleStructure(ctx.module); |
| 8578 | } |
| 8579 | dlclose(handle); |
| 8580 | serverLog(LL_WARNING, |
| 8581 | "Module %s initialization failed. Module not loaded",path); |
| 8582 | return C_ERR; |
| 8583 | } |
| 8584 | |
| 8585 | /* Redis module loaded! Register it. */ |
| 8586 | dictAdd(modules,ctx.module->name,ctx.module); |
| 8587 | ctx.module->blocked_clients = 0; |
| 8588 | ctx.module->handle = handle; |
| 8589 | serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path); |
| 8590 | /* Fire the loaded modules event. */ |
| 8591 | moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE, |
| 8592 | REDISMODULE_SUBEVENT_MODULE_LOADED, |
| 8593 | ctx.module); |
| 8594 | |
| 8595 | moduleFreeContext(&ctx); |
| 8596 | return C_OK; |
| 8597 | } |
| 8598 | |
| 8599 | |
| 8600 | /* Unload the module registered with the specified name. On success |
no test coverage detected