mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-27 02:26:21 +09:00
a48a42baf4
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>
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")
|
|
}
|
|
}
|