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. */
| 8604 | * * ENONET: No such module having the specified name. |
| 8605 | * * EBUSY: The module exports a new data type and can only be reloaded. */ |
| 8606 | int moduleUnload(sds name) { |
| 8607 | struct RedisModule *module = dictFetchValue(modules,name); |
| 8608 | |
| 8609 | if (module == NULL) { |
| 8610 | errno = ENOENT; |
| 8611 | return REDISMODULE_ERR; |
| 8612 | } else if (listLength(module->types)) { |
| 8613 | errno = EBUSY; |
| 8614 | return REDISMODULE_ERR; |
| 8615 | } else if (listLength(module->usedby)) { |
| 8616 | errno = EPERM; |
| 8617 | return REDISMODULE_ERR; |
| 8618 | } else if (module->blocked_clients) { |
| 8619 | errno = EAGAIN; |
| 8620 | return REDISMODULE_ERR; |
| 8621 | } |
| 8622 | |
| 8623 | /* Give module a chance to clean up. */ |
| 8624 | int (*onunload)(void *); |
| 8625 | onunload = (int (*)(void *))(unsigned long) dlsym(module->handle, "RedisModule_OnUnload"); |
| 8626 | if (onunload) { |
| 8627 | RedisModuleCtx ctx = REDISMODULE_CTX_INIT; |
| 8628 | ctx.module = module; |
| 8629 | ctx.client = moduleFreeContextReusedClient; |
| 8630 | int unload_status = onunload((void*)&ctx); |
| 8631 | moduleFreeContext(&ctx); |
| 8632 | |
| 8633 | if (unload_status == REDISMODULE_ERR) { |
| 8634 | serverLog(LL_WARNING, "Module %s OnUnload failed. Unload canceled.", name); |
| 8635 | errno = ECANCELED; |
| 8636 | return REDISMODULE_ERR; |
| 8637 | } |
| 8638 | } |
| 8639 | |
| 8640 | moduleFreeAuthenticatedClients(module); |
| 8641 | moduleUnregisterCommands(module); |
| 8642 | moduleUnregisterSharedAPI(module); |
| 8643 | moduleUnregisterUsedAPI(module); |
| 8644 | moduleUnregisterFilters(module); |
| 8645 | |
| 8646 | /* Remove any notification subscribers this module might have */ |
| 8647 | moduleUnsubscribeNotifications(module); |
| 8648 | moduleUnsubscribeAllServerEvents(module); |
| 8649 | |
| 8650 | /* Unload the dynamic library. */ |
| 8651 | if (dlclose(module->handle) == -1) { |
| 8652 | char *error = dlerror(); |
| 8653 | if (error == NULL) error = "Unknown error"; |
| 8654 | serverLog(LL_WARNING,"Error when trying to close the %s module: %s", |
| 8655 | module->name, error); |
| 8656 | } |
| 8657 | |
| 8658 | /* Fire the unloaded modules event. */ |
| 8659 | moduleFireServerEvent(REDISMODULE_EVENT_MODULE_CHANGE, |
| 8660 | REDISMODULE_SUBEVENT_MODULE_UNLOADED, |
| 8661 | module); |
| 8662 | |
| 8663 | /* Remove from list of modules. */ |
no test coverage detected