mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-30 03:49:36 +09:00
46a80ea8f9
After Remove/Rename, the extra-records filewatcher retried with
context.Background and the default 15-minute backoff budget, so Close
could not stop Run. Cancel that retry when closeCh closes. If the file
is still missing after the budget, watch the parent directory so a later
recreate is seen.
Close the fsnotify watcher on NewExtraRecordsManager error paths after
NewWatcher succeeds.
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
(cherry picked from commit a48a42baf4)
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package dns
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestUpdateRecordsDoesNotBlockShutdown ensures updateRecords does not park
|
|
// forever on the update channel during shutdown. The send must release the
|
|
// write lock first and abort on closeCh, otherwise the Run goroutine leaks and
|
|
// holds the lock indefinitely when no consumer is draining the channel.
|
|
func TestUpdateRecordsDoesNotBlockShutdown(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "extra.json")
|
|
require.NoError(t, os.WriteFile(path,
|
|
[]byte(`[{"name":"a.example.com","type":"A","value":"100.64.0.1"}]`), 0o600))
|
|
|
|
er, err := NewExtraRecordsManager(path)
|
|
require.NoError(t, err)
|
|
|
|
defer er.watcher.Close()
|
|
|
|
// Change the file so updateRecords passes the unchanged-hash guard and
|
|
// reaches the send with no consumer draining UpdateCh.
|
|
require.NoError(t, os.WriteFile(path,
|
|
[]byte(`[{"name":"b.example.com","type":"A","value":"100.64.0.2"}]`), 0o600))
|
|
|
|
done := make(chan struct{})
|
|
|
|
go func() {
|
|
er.updateRecords()
|
|
close(done)
|
|
}()
|
|
|
|
er.Close()
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("updateRecords parked on a blocking send and did not return after Close")
|
|
}
|
|
}
|
|
|
|
// TestWaitUntilPathExistsReturnsOnClose ensures Close unblocks the
|
|
// Remove/Rename retry. A missing extra-records file must not pin Run
|
|
// for the 15-minute backoff budget after shutdown.
|
|
func TestWaitUntilPathExistsReturnsOnClose(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "extra.json")
|
|
require.NoError(t, os.WriteFile(path,
|
|
[]byte(`[{"name":"a.example.com","type":"A","value":"100.64.0.1"}]`), 0o600))
|
|
|
|
er, err := NewExtraRecordsManager(path)
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, os.Remove(path))
|
|
|
|
done := make(chan error, 1)
|
|
|
|
go func() {
|
|
done <- er.waitUntilPathExists()
|
|
}()
|
|
|
|
er.Close()
|
|
|
|
select {
|
|
case err := <-done:
|
|
require.Error(t, err)
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("waitUntilPathExists did not return after Close while the extra-records file was missing")
|
|
}
|
|
}
|