Load a module and initialize it. On success C_OK is returned, otherwise * C_ERR is returned. */
| 8741 | /* Load a module and initialize it. On success C_OK is returned, otherwise |
| 8742 | * C_ERR is returned. */ |
| 8743 | int moduleLoad(const char *path, void **module_argv, int module_argc) { |
| 8744 | int (*onload)(void *, void **, int); |
| 8745 | void *handle; |
| 8746 | RedisModuleCtx ctx = REDISMODULE_CTX_INIT; |
| 8747 | ctx.client = moduleFreeContextReusedClient; |
| 8748 | selectDb(ctx.client, 0); |
| 8749 | |
| 8750 | struct stat st; |
| 8751 | if (stat(path, &st) == 0) |
| 8752 | { // this check is best effort |
| 8753 | if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { |
| 8754 | serverLog(LL_WARNING, "Module %s failed to load: It does not have execute permissions.", path); |
| 8755 | return C_ERR; |
| 8756 | } |
| 8757 | } |
| 8758 | |
| 8759 | handle = dlopen(path,RTLD_NOW|RTLD_LOCAL); |
| 8760 | if (handle == NULL) { |
| 8761 | serverLog(LL_WARNING, "Module %s failed to load: %s", path, dlerror()); |
| 8762 | return C_ERR; |
| 8763 | } |
| 8764 | onload = (int (*)(void *, void **, int))(unsigned long) dlsym(handle,"RedisModule_OnLoad"); |
| 8765 | if (onload == NULL) { |
| 8766 | dlclose(handle); |
| 8767 | serverLog(LL_WARNING, |
| 8768 | "Module %s does not export RedisModule_OnLoad() " |
| 8769 | "symbol. Module not loaded.",path); |
| 8770 | return C_ERR; |
| 8771 | } |
| 8772 | if (onload((void*)&ctx,module_argv,module_argc) == REDISMODULE_ERR) { |
| 8773 | if (ctx.module) { |
| 8774 | moduleUnregisterCommands(ctx.module); |
| 8775 | moduleUnregisterSharedAPI(ctx.module); |
| 8776 | moduleUnregisterUsedAPI(ctx.module); |
| 8777 | moduleFreeModuleStructure(ctx.module); |
| 8778 | } |
| 8779 | dlclose(handle); |
| 8780 | serverLog(LL_WARNING, |
| 8781 | "Module %s initialization failed. Module not loaded",path); |
| 8782 | return C_ERR; |
| 8783 | } |
| 8784 | |
| 8785 | /* Redis module loaded! Register it. */ |
| 8786 | dictAdd(modules,ctx.module->name,ctx.module); |
| 8787 | ctx.module->blocked_clients = 0; |
| 8788 | ctx.module->handle = handle; |
| 8789 | serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path); |
| 8790 | /* Fire the loaded modules event. */ |
| 8791 | moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE, |
| 8792 | REDISMODULE_SUBEVENT_MODULE_LOADED, |
| 8793 | ctx.module); |
| 8794 | |
| 8795 | moduleFreeContext(&ctx); |
| 8796 | return C_OK; |
| 8797 | } |
| 8798 | |
| 8799 | |
| 8800 | /* Unload the module registered with the specified name. On success |
no test coverage detected