Skip to content

drivers: on_task_change gets a NULL task status on ttl expiration #255

Description

@bigbes

In the "ttl tasks" loop of the fifottl and utubettl driver fibers the loop variable shadows the state module:

for_, stateinpairs(ttl_states) do
task=self.space.index.watch:min{ state }
iftask~=nilandtask[i_status] ==statethen
ifnow>=task[i_next_event] then
task=self:delete(task[i_id]):transform(2, 1, state.DONE)
self:on_task_change(task, 'ttl')

for_, stateinpairs(ttl_states) do
task=self.space.index.watch:min{ state }
iftask~=nilandtask[i_status] ==statethen
ifnow>=task[i_next_event] then
task=self:delete(task[i_id]):transform(2, 1, state.DONE)
self:on_task_change(task, 'ttl')

Inside the loop state is a status string, so state.DONE indexes a string and evaluates to nil. transform(2, 1, nil) then writes NULL into the status field instead of DONE:

tarantool> box.tuple.new{10, 'r', 111}:transform(2, 1, nil)
---
- [10, null, 111]
...

So the task passed to the user's on_task_change callback with the ttl event is malformed. Internal bookkeeping is unaffected: the READY/TAKEN branches in abstract.lua are skipped for a deleted task anyway and the statistics are still counted.

Steps to reproduce

localtube=queue.create_tube('t', 'fifottl', {ttl=0.1,
on_task_change=function(task, event)
ifevent=='ttl' thenrequire('log').info('status: %s', tostring(task[2])) endend})
tube:put('expired')

Actual behavior

status: cdata<void *>: NULL

Expected behavior

status: - (state.DONE)

Renaming the loop variable is enough.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions