Unload the module registered with the specified name. On success * C_OK is returned, otherwise C_ERR is returned and errno is set * to the following values depending on the type of error: * * * ENONET: No such module having the specified name. * * EBUSY: The module exports a new data type and can only be reloaded. */
| 8804 | * * ENONET: No such module having the specified name. |
| 8805 | * * EBUSY: The module exports a new data type and can only be reloaded. */ |
| 8806 | int moduleUnload(sds name) { |
| 8807 | struct RedisModule *module = (RedisModule*)dictFetchValue(modules,name); |
| 8808 | |
| 8809 | if (module == NULL) { |
| 8810 | errno = ENOENT; |
| 8811 | return REDISMODULE_ERR; |
| 8812 | } else if (listLength(module->types)) { |
| 8813 | errno = EBUSY; |
| 8814 | return REDISMODULE_ERR; |
| 8815 | } else if (listLength(module->usedby)) { |
| 8816 | errno = EPERM; |
| 8817 | return REDISMODULE_ERR; |
| 8818 | } else if (module->blocked_clients) { |
| 8819 | errno = EAGAIN; |
| 8820 | return REDISMODULE_ERR; |
| 8821 | } |
| 8822 | |
| 8823 | /* Give module a chance to clean up. */ |
| 8824 | int (*onunload)(void *); |
| 8825 | onunload = (int (*)(void *))(unsigned long) dlsym(module->handle, "RedisModule_OnUnload"); |
| 8826 | if (onunload) { |
| 8827 | RedisModuleCtx ctx = REDISMODULE_CTX_INIT; |
| 8828 | ctx.module = module; |
| 8829 | ctx.client = moduleFreeContextReusedClient; |
| 8830 | int unload_status = onunload((void*)&ctx); |
| 8831 | moduleFreeContext(&ctx); |
| 8832 | |
| 8833 | if (unload_status == REDISMODULE_ERR) { |
| 8834 | serverLog(LL_WARNING, "Module %s OnUnload failed. Unload canceled.", name); |
| 8835 | errno = ECANCELED; |
| 8836 | return REDISMODULE_ERR; |
| 8837 | } |
| 8838 | } |
| 8839 | |
| 8840 | moduleFreeAuthenticatedClients(module); |
| 8841 | moduleUnregisterCommands(module); |
| 8842 | moduleUnregisterSharedAPI(module); |
| 8843 | moduleUnregisterUsedAPI(module); |
| 8844 | moduleUnregisterFilters(module); |
| 8845 | |
| 8846 | /* Remove any notification subscribers this module might have */ |
| 8847 | moduleUnsubscribeNotifications(module); |
| 8848 | moduleUnsubscribeAllServerEvents(module); |
| 8849 | |
| 8850 | /* Unload the dynamic library. */ |
| 8851 | if (dlclose(module->handle) == -1) { |
| 8852 | const char *error = dlerror(); |
| 8853 | if (error == NULL) error = "Unknown error"; |
| 8854 | serverLog(LL_WARNING,"Error when trying to close the %s module: %s", |
| 8855 | module->name, error); |
| 8856 | } |
| 8857 | |
| 8858 | /* Fire the unloaded modules event. */ |
| 8859 | moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE, |
| 8860 | REDISMODULE_SUBEVENT_MODULE_UNLOADED, |
| 8861 | module); |
| 8862 | |
| 8863 | /* Remove from list of modules. */ |
no test coverage detected