Update Nginx lock discovery loop

https://github.com/webmin/webmin/pull/2842#discussion_r4039699490
This commit is contained in:
Ilia Ross
2026-09-17 20:14:42 +02:00
parent 1c80e8f298
commit afb0929dd9
2 changed files with 29 additions and 4 deletions

View File

@@ -551,8 +551,11 @@ if ($lock_all_config_files_depth) {
my $main = &resolve_links($config{'nginx_config'}) || $config{'nginx_config'};
my @files = ($main);
my %locked;
while (@files) {
# Repeat until a fresh parse finds no additional config files.
while (1) {
my $new_files = 0;
foreach my $f (@files) {
next if ($locked{$f});
my $pid = &test_lock($f);
if ($pid && $pid == $$) {
# Keep a lock taken by the caller outside our unlock list.
@@ -564,12 +567,15 @@ while (@files) {
&error("Failed to lock Nginx config file $f");
}
$locked{$f} = 1;
$new_files++;
&unflush_file_lines($f);
}
# Raw config edits lock included files independently. Re-read after
# acquiring each batch and lock any newly discovered includes.
last if (!$new_files);
# An included file may change while this process waits for its lock.
# Reparse after each batch to find any newly included files.
&flush_config_cache();
@files = grep { !$locked{$_} } &unique(&get_all_config_files(),
@files = &unique(&get_all_config_files(),
$parent ? &get_all_config_files($parent) : ());
}
$lock_all_config_files_depth = 1;

View File

@@ -163,4 +163,23 @@ subtest 'included files are refreshed after waiting for their locks' => sub {
main::unlock_all_config_files();
};
subtest 'a parent block can span included files' => sub {
write_text($included, "listen 80;\n");
write_text($conf,
"http {\n".
" server {\n".
" server_name parent.invalid;\n".
" include $included;\n".
" }\n".
"}\n");
main::flush_config_cache();
my $parent = server('parent.invalid');
is_deeply([sort(main::get_all_config_files($parent))],
[sort($conf, $included)], 'parent spans both config files');
main::lock_all_config_files($parent);
ok(-e "$conf.lock" && -e "$included.lock",
'parent lock covers both config files');
main::unlock_all_config_files();
};
done_testing();