Skip to content

forbid module to unload when it holds ongoing timer#10187

Merged
oranagra merged 9 commits into
redis:unstablefrom
warriorguo:forbidmoduleongoingtimer
Feb 1, 2022
Merged

forbid module to unload when it holds ongoing timer#10187
oranagra merged 9 commits into
redis:unstablefrom
warriorguo:forbidmoduleongoingtimer

Conversation

@warriorguo

@warriorguo warriorguo commented Jan 26, 2022

Copy link
Copy Markdown
Contributor

This is done to avoid a crash when the timer fires after the module was unloaded.
Or memory leaks in case we wanted to just ignore the timer.
It'll cause the MODULE UNLOAD command to return with an error
fix #10186

Comment thread tests/unit/moduleapi/timer.tcl Outdated
Comment thread tests/unit/moduleapi/timer.tcl Outdated
Comment thread src/module.c Outdated
@sundb

sundb commented Jan 26, 2022

Copy link
Copy Markdown
Collaborator

@warriorguo It looks like missing a test for module unload while the timer is still running.

@warriorguo

Copy link
Copy Markdown
Contributor Author

@sundb thanks for the review, actually I tried to add a test for unloading as it would return an error, but it would be caught by (https://github.com/redis/redis/blob/unstable/tests/test_helper.tcl#L850) and caused the failure. Any suggestions for this situation?

@sundb

sundb commented Jan 26, 2022

Copy link
Copy Markdown
Collaborator

@warriorguo You can post or commit your test code, I will help to see it.

Comment thread src/module.c Outdated
Comment thread tests/unit/moduleapi/timer.tcl Outdated
@warriorguo

Copy link
Copy Markdown
Contributor Author

@sundb please check 2f8fd8a. the failure message was something like.

[exception]: Executing test client: ERR Error unloading module: operation not possible..
ERR Error unloading module: operation not possible.
    while executing
"[srv $level "client"] {*}$args"
    (procedure "r" line 7)
    invoked from within
"r module unload timer"
    ("uplevel" body line 8)
    invoked from within
"uplevel 1 $code"
    (procedure "test" line 51)
    invoked from within
"test "Module can be unloaded only when timer was finished" {
        r set "timer-incr-key" 0
        set id [r test.createtimer 2000 timer-incr-key]
..."
    ("uplevel" body line 57)
    invoked from within
"uplevel 1 $code "
    (procedure "start_server" line 3)
    invoked from within
"start_server {tags {"modules"}} {
    r module load $testmodule

    test {RM_CreateTimer: a sequence of timers work} {
        # We can't guarantee s..."
    (file "tests/unit/moduleapi/timer.tcl" line 3)
    invoked from within
"source $path"
    (procedure "execute_test_file" line 4)
    invoked from within
"execute_test_file $data"
    (procedure "test_client_main" line 10)
    invoked from within
"test_client_main $::test_server_port "

thanks in advance!

Comment thread tests/unit/moduleapi/timer.tcl
@oranagra

Copy link
Copy Markdown
Member

@warriorguo @sundb isn't it better to delete the timer when the module is unloaded (rather than refuse the module unload)?

@sundb

sundb commented Jan 26, 2022

Copy link
Copy Markdown
Collaborator

@oranagra I thought about that, but I saw that returned an error when blocked_clients was not empty, and I gave up on that idea.

Comment thread src/module.c
@warriorguo

Copy link
Copy Markdown
Contributor Author

@oranagra in the test case, deleting the timer directly would cause the memory leaks as well, to the ones were held by the parameter.

@zuiderkwast

Copy link
Copy Markdown
Contributor

@oranagra in the test case, deleting the timer directly would cause the memory leaks as well, to the ones were held by the parameter.

The keyname here is leaked? User data provided to the timer needs to be freed...

    RedisModuleString *keyname;
    if (RedisModule_StopTimer(ctx, id, (void **) &keyname) == REDISMODULE_OK) {
        RedisModule_FreeString(ctx, keyname);

@warriorguo

Copy link
Copy Markdown
Contributor Author

@zuiderkwast yes, in the case, if the timer was deleted automatically when the module unload, the user data would be leaked that would have been supposed to be handled at (https://github.com/redis/redis/blob/unstable/tests/modules/timer.c#L12)

Comment thread src/module.c Outdated
Co-authored-by: sundb <sundbcn@gmail.com>
Comment thread tests/unit/moduleapi/timer.tcl Outdated
@oranagra

oranagra commented Feb 1, 2022

Copy link
Copy Markdown
Member

triggered daily CI cycle for module tests:
https://github.com/redis/redis/actions/runs/1778235529

@oranagra oranagra merged commit 6b5b3ca into redis:unstable Feb 1, 2022
@oranagra oranagra added the release-notes indication that this issue needs to be mentioned in the release notes label Feb 1, 2022
@oranagra oranagra mentioned this pull request Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes indication that this issue needs to be mentioned in the release notes

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

[CRASH] unfinished module timer causes crash after the module unload

5 participants