Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package opentofu for openSUSE:Factory 
checked in at 2025-08-04 15:22:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/opentofu (Old)
 and      /work/SRC/openSUSE:Factory/.opentofu.new.1085 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "opentofu"

Mon Aug  4 15:22:43 2025 rev:36 rq:1297239 version:1.10.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/opentofu/opentofu.changes        2025-08-02 
00:44:36.709674773 +0200
+++ /work/SRC/openSUSE:Factory/.opentofu.new.1085/opentofu.changes      
2025-08-04 15:23:28.658588092 +0200
@@ -1,0 +2,11 @@
+Sun Aug 03 11:30:39 UTC 2025 - Johannes Kastl 
<opensuse_buildserv...@ojkastl.de>
+
+- Update to version 1.10.5:
+  * BUG FIXES:
+    - Fixed issue where usage of TF_PLUGIN_CACHE_DIR could result
+      in unexpected lock contention errors (#3090)
+      NOTE: It is still highly recommended to have valid
+      .terraform.lock.hcl files in projects using
+      TF_PLUGIN_CACHE_DIR
+
+-------------------------------------------------------------------

Old:
----
  opentofu-1.10.4.obscpio

New:
----
  opentofu-1.10.5.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ opentofu.spec ++++++
--- /var/tmp/diff_new_pack.PykhKy/_old  2025-08-04 15:23:30.894683408 +0200
+++ /var/tmp/diff_new_pack.PykhKy/_new  2025-08-04 15:23:30.894683408 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package opentofu
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2025 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %define executable_name tofu
 
 Name:           opentofu
-Version:        1.10.4
+Version:        1.10.5
 Release:        0
 Summary:        Declaratively manage your cloud infrastructure
 License:        MPL-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.PykhKy/_old  2025-08-04 15:23:30.930684942 +0200
+++ /var/tmp/diff_new_pack.PykhKy/_new  2025-08-04 15:23:30.934685113 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/opentofu/opentofu/</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.10.4</param>
+    <param name="revision">v1.10.5</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.PykhKy/_old  2025-08-04 15:23:30.958686135 +0200
+++ /var/tmp/diff_new_pack.PykhKy/_new  2025-08-04 15:23:30.962686306 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/opentofu/opentofu/</param>
-              <param 
name="changesrevision">6d6c2fa96497c15fd8d0b46dc8db0e6877a88b1b</param></service></servicedata>
+              <param 
name="changesrevision">20e08688ca2891c0d9398fbc3714aa4847f2cfb3</param></service></servicedata>
 (No newline at EOF)
 

++++++ opentofu-1.10.4.obscpio -> opentofu-1.10.5.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.10.4/CHANGELOG.md 
new/opentofu-1.10.5/CHANGELOG.md
--- old/opentofu-1.10.4/CHANGELOG.md    2025-07-31 15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/CHANGELOG.md    2025-08-01 16:20:32.000000000 +0200
@@ -1,6 +1,13 @@
-## 1.10.4 (unreleased)
+## 1.10.6 (unreleased)
 
-## 1.10.3
+## 1.10.5
+
+BUG FIXES:
+
+- Fixed issue where usage of TF_PLUGIN_CACHE_DIR could result in unexpected 
lock contention errors ([#3090](https://github.com/opentofu/opentofu/pull/3090))
+  - NOTE: It is still highly recommended to have valid .terraform.lock.hcl 
files in projects using TF_PLUGIN_CACHE_DIR
+
+## 1.10.4
 
 BUG FIXES:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.10.4/internal/command/init.go 
new/opentofu-1.10.5/internal/command/init.go
--- old/opentofu-1.10.4/internal/command/init.go        2025-07-31 
15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/internal/command/init.go        2025-08-01 
16:20:32.000000000 +0200
@@ -905,6 +905,9 @@
                                c.Ui.Info(fmt.Sprintf("- Installed %s v%s 
(%s%s)", provider.ForDisplay(), version, authResult, keyID))
                        }
                },
+               CacheDirLockContended: func(cacheDir string) {
+                       c.Ui.Info(fmt.Sprintf("- Waiting for lock on cache 
directory %s", cacheDir))
+               },
                ProvidersLockUpdated: func(provider addrs.Provider, version 
getproviders.Version, localHashes []getproviders.Hash, signedHashes 
[]getproviders.Hash, priorHashes []getproviders.Hash) {
                        // We're going to use this opportunity to track if we 
have any
                        // "incomplete" installs of providers. An incomplete 
install is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.10.4/internal/flock/filesystem_lock_unix.go 
new/opentofu-1.10.5/internal/flock/filesystem_lock_unix.go
--- old/opentofu-1.10.4/internal/flock/filesystem_lock_unix.go  2025-07-31 
15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/internal/flock/filesystem_lock_unix.go  2025-08-01 
16:20:32.000000000 +0200
@@ -9,6 +9,8 @@
 package flock
 
 import (
+       "context"
+       "fmt"
        "io"
        "os"
        "syscall"
@@ -27,6 +29,66 @@
        return syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, flock)
 }
 
+// LockBlocking is like Lock except that if the lock is currently contended
+// then it blocks until it becomes available.
+//
+// If the given context is cancelled then it returns early with the 
cancellation
+// error.
+func LockBlocking(ctx context.Context, f *os.File) error {
+       flock := &syscall.Flock_t{
+               Type:   syscall.F_RDLCK | syscall.F_WRLCK,
+               Whence: int16(io.SeekStart),
+               Start:  0,
+               Len:    0,
+       }
+
+       ctx, cancel := context.WithCancel(ctx)
+       defer cancel()
+
+       c := make(chan error)
+       go func() {
+               for {
+                       err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLKW, 
flock)
+                       if err == syscall.EINTR {
+                               // We'll get here if our process gets any 
signal at all, but
+                               // not all signals represent cancellation.
+                               if ctxErr := ctx.Err(); ctxErr != nil {
+                                       err = ctxErr // return the cancellation 
error instead of generic EINTR
+                               } else {
+                                       continue // not cancelled yet
+                               }
+                       }
+                       c <- err
+                       close(c)
+                       return
+               }
+       }()
+
+       for {
+               select {
+               case err := <-c:
+                       return err
+               case <-ctx.Done():
+                       // We will get here if the cancellation is caused by 
anything other
+                       // than a Unix signal, in which case we'll send a 
signal ourselves
+                       // to force the waiting goroutine to exit.
+                       // We use SIGUSR1 here on the assumption that nothing 
else in
+                       // OpenTofu uses it. We're sending this to the current 
pid
+                       // explicitly because we might have other processes, 
such as
+                       // plugins, also running in our process group (which is 
what we'd
+                       // signal if using pid 0 here).
+                       err := syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+                       if err != nil {
+                               // This should not fail, but if it does then 
we'd otherwise
+                               // get hung up here and so we'll return an 
error and accept
+                               // that our background goroutine is going to 
just hang around
+                               // until another signal shows up or the program 
exits.
+                               return fmt.Errorf("failed canceling lock 
acquisition: %w", err)
+                       }
+               }
+       }
+}
+
 func Unlock(f *os.File) error {
        flock := &syscall.Flock_t{
                Type:   syscall.F_UNLCK,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.10.4/internal/flock/filesystem_lock_windows.go 
new/opentofu-1.10.5/internal/flock/filesystem_lock_windows.go
--- old/opentofu-1.10.4/internal/flock/filesystem_lock_windows.go       
2025-07-31 15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/internal/flock/filesystem_lock_windows.go       
2025-08-01 16:20:32.000000000 +0200
@@ -9,9 +9,12 @@
 package flock
 
 import (
+       "context"
+       "errors"
        "math"
        "os"
        "syscall"
+       "time"
        "unsafe"
 )
 
@@ -26,6 +29,8 @@
        // 
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 alows the file handle to be opened by another process for 
competing locks on the same file.
@@ -48,6 +53,44 @@
        )
 }
 
+// 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
+                               return
+                       }
+
+                       select {
+                       case <-ctx.Done():
+                               // Lock cancelled, so return cancellation error
+                               resultChan <- ctx.Err()
+                               return
+                       default:
+                               // LockFileEx returns this error when the lock 
is contended.
+                               var errno syscall.Errno
+                               ok := errors.As(err, &errno)
+                               if ok && errno == ERROR_LOCK_VIOLATION {
+                                       // Chill for a bit before trying again
+                                       time.Sleep(100 * time.Millisecond)
+                                       continue
+                               }
+                               // All other errors are fatal.
+                               resultChan <- err
+                       }
+               }
+       }()
+
+       return <-resultChan
+}
+
 func Unlock(*os.File) error {
        // the lock is released when Close() is called
        return nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.10.4/internal/providercache/dir_modify.go 
new/opentofu-1.10.5/internal/providercache/dir_modify.go
--- old/opentofu-1.10.4/internal/providercache/dir_modify.go    2025-07-31 
15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/internal/providercache/dir_modify.go    2025-08-01 
16:20:32.000000000 +0200
@@ -151,34 +151,25 @@
                return nil, err
        }
 
-       // Wait for the file lock for up to 60s.  Might make sense to have the 
timeout be configurable for different network conditions / package sizes.
-       for timeout := time.After(time.Second * 60); ; {
-               // We have a valid file handle, let's try to lock it 
(nonblocking)
-               err := flock.Lock(f)
-               if err == nil {
-                       // Lock succeeded
-                       break
-               }
-
-               select {
-               case <-timeout:
-                       if f != nil {
-                               f.Close()
-                       }
-                       return nil, fmt.Errorf("unable to acquire file lock on 
%q: %w", lockFile, err)
-               case <-ctx.Done():
-                       if f != nil {
-                               f.Close()
-                       }
-                       return nil, ctx.Err()
-               default:
-                       // Chill for a bit before trying again
-                       time.Sleep(100 * time.Millisecond)
-               }
-
+       // If the callers InstallerEvents has a hook function for
+       // CacheDirLockContended then we'll notify it if we take more than five
+       // seconds to acquire the lock, to give some feedback about what's 
causing
+       // delay here. 5 seconds is an arbitrary amount that's short enough to
+       // give relatively prompt feedback but long enough to be reasonably
+       // confident that a delay here is caused by lock contention.
+       evts := installerEventsForContext(ctx)
+       if evts.CacheDirLockContended != nil {
+               cancelWhenSlow := whenSlow(5*time.Second, func() {
+                       evts.CacheDirLockContended(d.BasePath())
+               })
+               defer cancelWhenSlow()
        }
 
-       log.Printf("[TRACE] Acquired global provider lock %s", lockFile)
+       err = flock.LockBlocking(ctx, f)
+       if err != nil {
+               // Ensure that we are not in a partially failed state
+               return nil, fmt.Errorf("unable to acquire file lock on %q: %w", 
lockFile, err)
+       }
 
        return func() error {
                log.Printf("[TRACE] Releasing global provider lock %s", 
lockFile)
@@ -193,3 +184,17 @@
                return unlockErr
        }, nil
 }
+
+func whenSlow(dur time.Duration, f func()) (cancel func()) {
+       cancelCh := make(chan struct{})
+       go func() {
+               select {
+               case <-cancelCh:
+               case <-time.After(dur):
+                       f()
+               }
+       }()
+       return func() {
+               close(cancelCh)
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.10.4/internal/providercache/installer_events.go 
new/opentofu-1.10.5/internal/providercache/installer_events.go
--- old/opentofu-1.10.4/internal/providercache/installer_events.go      
2025-07-31 15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/internal/providercache/installer_events.go      
2025-08-01 16:20:32.000000000 +0200
@@ -112,6 +112,11 @@
        FetchPackageSuccess func(provider addrs.Provider, version 
getproviders.Version, localDir string, authResult 
*getproviders.PackageAuthenticationResult)
        FetchPackageFailure func(provider addrs.Provider, version 
getproviders.Version, err error)
 
+       // CacheDirLockContended is called if acquiring a lock on the specified
+       // cache directory takes more than a few seconds, suggesting that some
+       // other process is already holding a lock.
+       CacheDirLockContended func(cacheDir string)
+
        // The ProvidersLockUpdated event is called whenever the lock file will 
be
        // updated. It provides the following information:
        //
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.10.4/version/VERSION 
new/opentofu-1.10.5/version/VERSION
--- old/opentofu-1.10.4/version/VERSION 2025-07-31 15:22:01.000000000 +0200
+++ new/opentofu-1.10.5/version/VERSION 2025-08-01 16:20:32.000000000 +0200
@@ -1 +1 @@
-1.10.4
+1.10.5

++++++ opentofu.obsinfo ++++++
--- /var/tmp/diff_new_pack.PykhKy/_old  2025-08-04 15:23:33.074776336 +0200
+++ /var/tmp/diff_new_pack.PykhKy/_new  2025-08-04 15:23:33.078776506 +0200
@@ -1,5 +1,5 @@
 name: opentofu
-version: 1.10.4
-mtime: 1753968121
-commit: 6d6c2fa96497c15fd8d0b46dc8db0e6877a88b1b
+version: 1.10.5
+mtime: 1754058032
+commit: 20e08688ca2891c0d9398fbc3714aa4847f2cfb3
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/opentofu/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.opentofu.new.1085/vendor.tar.gz differ: char 20, 
line 1

Reply via email to