Skip to content

Commit d165f2f

Browse files
committed
try to fix "access denied" error when starting up game first time with sndbox
1 parent 5537d77 commit d165f2f

File tree

1 file changed

+54
-25
lines changed

1 file changed

+54
-25
lines changed

runner/fuji_windows.go

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
package runner
44

55
import (
6+
"errors"
67
"fmt"
8+
"os"
79
"path/filepath"
810
"strings"
11+
"time"
912

1013
"github.com/itchio/headway/state"
1114
"github.com/itchio/ox/syscallex"
@@ -103,33 +106,59 @@ func (wr *fujiRunner) Run() error {
103106

104107
defer sp.Revoke(consumer)
105108

106-
cmd := execas.Command(params.FullTargetPath, params.Args...)
107-
cmd.Username = creds.Username
108-
cmd.Domain = "."
109-
cmd.Password = creds.Password
110-
cmd.Dir = params.Dir
111-
cmd.Env = env
112-
cmd.Stdout = params.Stdout
113-
cmd.Stderr = params.Stderr
114-
115-
var creationFlags uint32 = syscallex.CREATE_SUSPENDED
116-
if params.Console {
117-
// note: this will disable std{in,out,err} redirection
118-
creationFlags |= syscallex.CREATE_NEW_CONSOLE
119-
}
120-
cmd.SysProcAttr = &syscallex.SysProcAttr{
121-
CreationFlags: creationFlags,
122-
LogonFlags: syscallex.LOGON_WITH_PROFILE,
123-
}
109+
const maxStartAttempts = 7
110+
const startRetryDelay = 1 * time.Second
111+
112+
var cmd *execas.Cmd
113+
var pg *processGroup
114+
115+
for attempt := 1; attempt <= maxStartAttempts; attempt++ {
116+
cmd = execas.Command(params.FullTargetPath, params.Args...)
117+
cmd.Username = creds.Username
118+
cmd.Domain = "."
119+
cmd.Password = creds.Password
120+
cmd.Dir = params.Dir
121+
cmd.Env = env
122+
cmd.Stdout = params.Stdout
123+
cmd.Stderr = params.Stderr
124+
125+
var creationFlags uint32 = syscallex.CREATE_SUSPENDED
126+
if params.Console {
127+
// note: this will disable std{in,out,err} redirection
128+
creationFlags |= syscallex.CREATE_NEW_CONSOLE
129+
}
130+
cmd.SysProcAttr = &syscallex.SysProcAttr{
131+
CreationFlags: creationFlags,
132+
LogonFlags: syscallex.LOGON_WITH_PROFILE,
133+
}
124134

125-
pg, err := NewProcessGroup(consumer, cmd, params.Ctx)
126-
if err != nil {
127-
return fmt.Errorf("%w", err)
128-
}
135+
pg, err = NewProcessGroup(consumer, cmd, params.Ctx)
136+
if err != nil {
137+
return fmt.Errorf("%w", err)
138+
}
129139

130-
err = cmd.Start()
131-
if err != nil {
132-
return fmt.Errorf("%w", err)
140+
err = cmd.Start()
141+
if err != nil {
142+
// After granting ACL permissions, Windows may not have fully
143+
// propagated them yet. Retry on access denied errors since the
144+
// permissions will become effective shortly.
145+
if errors.Is(err, os.ErrPermission) && attempt < maxStartAttempts {
146+
consumer.Warnf("Access denied on attempt %d/%d, retrying in %v...", attempt, maxStartAttempts, startRetryDelay)
147+
if params.Ctx != nil {
148+
select {
149+
case <-time.After(startRetryDelay):
150+
case <-params.Ctx.Done():
151+
return fmt.Errorf("%w", params.Ctx.Err())
152+
}
153+
} else {
154+
time.Sleep(startRetryDelay)
155+
}
156+
continue
157+
}
158+
return fmt.Errorf("%w", err)
159+
}
160+
161+
break
133162
}
134163

135164
err = pg.AfterStart()

0 commit comments

Comments
 (0)