Skip to content

Commit cb7cfa5

Browse files
gqcnCopilot
andauthored
fix: guard os.Args access for wasm which panics when building (gogf#4762)
This pull request improves the reliability and safety of server restart and reload operations by ensuring the correct retrieval of the current executable path and process arguments. It replaces direct usage of `os.Args[0]` with a more robust approach using `gfile.SelfPath()`, and adds error handling for cases where the executable path cannot be determined. Additionally, it introduces a helper function to safely obtain process arguments, and removes an unnecessary import. **Executable Path Handling and Error Checking:** - Replaced usage of `os.Args[0]` with `gfile.SelfPath()` throughout the server admin and process management code to reliably determine the current executable path; added checks and error responses when the path cannot be determined. [[1]](diffhunk://#diff-0d174b149c56c4aa7ffeba2be94d16dc1b8000933f1f2a2e6bf011acdad3272fL122-R134) [[2]](diffhunk://#diff-0d174b149c56c4aa7ffeba2be94d16dc1b8000933f1f2a2e6bf011acdad3272fL168-R184) [[3]](diffhunk://#diff-3b4265be7ef0335b832dacfc2fc7ddc0f9dfae5b81340ff57d2b6a526c60d9e1L62-R65) - Added early returns in initialization functions if `os.Args` is empty, preventing potential panics or misbehavior when the argument list is missing. [[1]](diffhunk://#diff-0aa99f033274ea60b9c466ae4fc98d0816ec13781d8ec787fb3ef106a49a79ecR35-R37) [[2]](diffhunk://#diff-5782fa47aa858b8e8358fd50353b050ee30418b7844b36e313e9c6d01188c092R47-R49) **Process Argument Handling:** - Introduced the `getCurrentProcessArgs()` helper function to safely return process arguments (excluding the program name), ensuring correct behavior even if no arguments are provided. Updated process creation calls to use this helper. **Code Cleanup:** - Removed an unused import of the `os` package from `ghttp_server_admin.go`. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 1878202 commit cb7cfa5

4 files changed

Lines changed: 34 additions & 6 deletions

File tree

debug/gdebug/gdebug_caller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ func init() {
3232
if goRootForFilter != "" {
3333
goRootForFilter = strings.ReplaceAll(goRootForFilter, "\\", "/")
3434
}
35+
if len(os.Args) == 0 {
36+
return
37+
}
3538
// Initialize internal package variable: selfPath.
3639
selfPath, _ = exec.LookPath(os.Args[0])
3740
if selfPath != "" {

net/ghttp/ghttp_server_admin.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package ghttp
88

99
import (
1010
"context"
11-
"os"
1211
"strings"
1312
"time"
1413

@@ -59,7 +58,11 @@ func (p *utilAdmin) Restart(r *Request) {
5958
// Custom start binary path when this process exits.
6059
path := r.GetQuery("newExeFilePath").String()
6160
if path == "" {
62-
path = os.Args[0]
61+
path = gfile.SelfPath()
62+
}
63+
if path == "" {
64+
r.Response.WriteExit("cannot determine current executable path")
65+
return
6366
}
6467
if err = RestartAllServer(ctx, path); err == nil {
6568
r.Response.WriteExit("server restarted")

net/ghttp/ghttp_server_admin_process.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,25 @@ func checkActionFrequency() error {
119119
// forkReloadProcess creates a new child process and copies the fd to child process.
120120
func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error {
121121
var (
122-
binaryPath = os.Args[0]
122+
binaryPath = gfile.SelfPath()
123123
)
124124
if len(newExeFilePath) > 0 && newExeFilePath[0] != "" {
125125
binaryPath = newExeFilePath[0]
126126
}
127+
if binaryPath == "" {
128+
return gerror.NewCodef(
129+
gcode.CodeInvalidOperation,
130+
"cannot determine current executable path: gfile.SelfPath() returned empty and no executable override was provided (goos=%s, goarch=%s, overrideProvided=%t)",
131+
runtime.GOOS,
132+
runtime.GOARCH,
133+
len(newExeFilePath) > 0 && newExeFilePath[0] != "",
134+
)
135+
}
127136
if !gfile.Exists(binaryPath) {
128137
return gerror.Newf(`binary file path "%s" does not exist`, binaryPath)
129138
}
130139
var (
131-
p = gproc.NewProcess(binaryPath, os.Args[1:], os.Environ())
140+
p = gproc.NewProcess(binaryPath, getCurrentProcessArgs(), os.Environ())
132141
sfm = getServerFdMap()
133142
)
134143
for name, m := range sfm {
@@ -165,17 +174,20 @@ func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error {
165174
// forkRestartProcess creates a new server process.
166175
func forkRestartProcess(ctx context.Context, newExeFilePath ...string) error {
167176
var (
168-
path = os.Args[0]
177+
path = gfile.SelfPath()
169178
)
170179
if len(newExeFilePath) > 0 && newExeFilePath[0] != "" {
171180
path = newExeFilePath[0]
172181
}
182+
if path == "" {
183+
return gerror.NewCode(gcode.CodeInvalidOperation, "cannot determine current executable path")
184+
}
173185
if err := os.Unsetenv(adminActionReloadEnvKey); err != nil {
174186
intlog.Errorf(ctx, `%+v`, err)
175187
}
176188
env := os.Environ()
177189
env = append(env, adminActionRestartEnvKey+"=1")
178-
p := gproc.NewProcess(path, os.Args[1:], env)
190+
p := gproc.NewProcess(path, getCurrentProcessArgs(), env)
179191
if _, err := p.Start(ctx); err != nil {
180192
glog.Errorf(
181193
ctx,
@@ -187,6 +199,13 @@ func forkRestartProcess(ctx context.Context, newExeFilePath ...string) error {
187199
return nil
188200
}
189201

202+
func getCurrentProcessArgs() []string {
203+
if len(os.Args) > 1 {
204+
return os.Args[1:]
205+
}
206+
return nil
207+
}
208+
190209
// getServerFdMap returns all the servers name to file descriptor mapping as map.
191210
func getServerFdMap() map[string]listenerFdMap {
192211
sfm := make(map[string]listenerFdMap)

os/gfile/gfile.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ var (
4444
)
4545

4646
func init() {
47+
if len(os.Args) == 0 {
48+
return
49+
}
4750
// Initialize internal package variable: selfPath.
4851
selfPath, _ = exec.LookPath(os.Args[0])
4952
if selfPath != "" {

0 commit comments

Comments
 (0)