Repository: opentofu/opentofu
File: internal/flock/filesystem_lock_windows.go (Go)

Code before:
	modkernel32      = syscall.NewLazyDLL("kernel32.dll")
	procLockFileEx   = modkernel32.NewProc("LockFileEx")
	procCreateEventW = modkernel32.NewProc("CreateEventW")
)

const (
	// dwFlags defined for LockFileEx
	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
	_LOCKFILE_FAIL_IMMEDIATELY = 1
	_LOCKFILE_EXCLUSIVE_LOCK   = 2
	// https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
	ERROR_LOCK_VIOLATION = 33
)

// This still allows the file handle to be opened by another process for competing locks on the same file.
func Lock(f *os.File) error {
	// even though we're failing immediately, an overlapped event structure is
	// required
	ol, err := newOverlapped()
	if err != nil {
		return err
	}
	defer func() {
		err := syscall.CloseHandle(ol.HEvent)
		if err != nil {
			log.Printf("failed to close handle: %v", err)
		}
	}()

	return lockFileEx(
		syscall.Handle(f.Fd()),
		_LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY,
		0,              // reserved
		0,              // bytes low
		math.MaxUint32, // bytes high
		ol,
	)
}

// This is a poor implementation of blocking locks, but it a somewhat function patch for the moment.
// This should eventually be tweaked to use native windows locking.
// See https://github.com/opentofu/opentofu/issues/3089 for more details.
func LockBlocking(ctx context.Context, f *os.File) error {
	resultChan := make(chan error)

	go func() {
		for {
			err := Lock(f)
			if err == nil {
				// Lock succeeded
				resultChan <- nil

Review comment (bug):
Normally when we use `log` in this codebase we use a log level prefix and include some context about what caused the log line, so maybe...

```suggestion
			log.Printf("[ERROR] failed to close file locking event handle: %v", err)
```

This is not a very specific "context" but probably the best we can do from here since this function doesn't know anything about what's its doing other than that it somehow involves locking. At least it's a relatively distinct string that would come up in code search if someone searched for it. 🤷‍♂️ 



Code after:
	modkernel32      = syscall.NewLazyDLL("kernel32.dll")
	procLockFileEx   = modkernel32.NewProc("LockFileEx")
	procCreateEventW = modkernel32.NewProc("CreateEventW")
)

const (
	// dwFlags defined for LockFileEx
	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
	_LOCKFILE_FAIL_IMMEDIATELY = 1
	_LOCKFILE_EXCLUSIVE_LOCK   = 2
	// https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
	ERROR_LOCK_VIOLATION = 33
)

// This still allows the file handle to be opened by another process for competing locks on the same file.
func Lock(f *os.File) error {
	// even though we're failing immediately, an overlapped event structure is
	// required
	ol, err := newOverlapped()
	if err != nil {
		return err
	}
	defer func() {
		err := syscall.CloseHandle(ol.HEvent)
		if err != nil {
			log.Printf("[ERROR] failed to close file locking event handle: %v", err)
		}
	}()

	return lockFileEx(
		syscall.Handle(f.Fd()),
		_LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY,
		0,              // reserved
		0,              // bytes low
		math.MaxUint32, // bytes high
		ol,
	)
}

// This is a poor implementation of blocking locks, but it a somewhat function patch for the moment.
// This should eventually be tweaked to use native windows locking.
// See https://github.com/opentofu/opentofu/issues/3089 for more details.
func LockBlocking(ctx context.Context, f *os.File) error {
	resultChan := make(chan error)

	go func() {
		for {
			err := Lock(f)
			if err == nil {
				// Lock succeeded
				resultChan <- nil