Skip to content

disk_log:chunk/3 is looping after the log file size has been reduced #9707

@ken2057

Description

@ken2057

Describe the bug
The issue occurs when the following conditions are met:

  1. the number of log file config being reduced via disk_log:change_size/2
  2. the number of exists log greater than the new size (e.g. old size is 10, and it has 7 logs exists, but user reduce the config size to 3)
  3. disk_log:change_size/2 is called 2 times. (The first time it keeps the old size and new size in a tuple, but the second time it only saves the new log size.)
  4. A function is looping to get the last log line using disk_log:chunk/3 and expects to reach the end of the loop when it encounters eof.

And when the loop function trying to get the last log line,
disk_log didn't know about the old size (due to 3th condition) then when it reaching the last file of new size but didn't has eof then disk_log will go back to the first file instead,
(e.g. when it reaching 5th log, it will go back to the 1st log instead)
due to eof only exist in the last file of old size (e.g. at the 7th log) so it will never able to find it with the new size and the loop function will be hanging.

To Reproduce
The reproduce can be run with this module.

-module(bug_disk_log).
-compile(export_all).

%% c(bug_disk_log), bug_disk_log:run().

-include_lib("eunit/include/eunit.hrl").

run() ->
    file:del_dir_r("./stream"),
    file:make_dir("./stream"),

    {ok, Log} = disk_log:open([{name, <<"dummy">>},
                               {type, wrap},
                               {file, "./stream/dummy"},
                               {size, {1, 10}}]),
    [disk_log:log(Log, {notif, N, N}) || N <- lists:seq(1, 7)],

    disk_log:change_size(Log, {1, 3}),
    %% the second disk_log:change_size will make
    %% the looping fun with disk_log:chunk/3 loop forever
    disk_log:change_size(Log, {1, 3}), %% comment this line to make the test pass

    F = fun GetEof(_Cont, 20) ->
                looping;
            GetEof(Cont, N) ->
                case disk_log:chunk(Log, Cont, 10) of
                    eof ->
                        ok;
                    {Cont1, _} ->
                        GetEof(Cont1, N + 1)
                end
        end,

    ?assertEqual(ok, F(start, 0)),

    file:del_dir_r("./stream"),
    disk_log:close(Log),
    ok.

Expected behavior
disk_log should cleanup for the exists log when file size is reduced.

Affected versions
27.3.2

Metadata

Metadata

Assignees

Labels

bugIssue is reported as a bugteam:PSAssigned to OTP team PS

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions