mem leak fix

This commit is contained in:
Sky Johnson 2025-03-19 20:24:47 -05:00
parent 55f27c6f68
commit 03a03af96c
2 changed files with 24 additions and 15 deletions

View File

@ -3,7 +3,6 @@ package runner
import (
"context"
"errors"
"path/filepath"
"sync"
"sync/atomic"
@ -29,7 +28,7 @@ type LuaRunner struct {
initFunc StateInitFunc // Optional function to initialize Lua state
bufferSize int // Size of the job queue buffer
requireCache *RequireCache // Cache for required modules
requireCfg RequireConfig // Configuration for require paths
requireCfg *RequireConfig // Configuration for require paths
scriptDir string // Base directory for scripts
libDirs []string // Additional library directories
}
@ -40,7 +39,7 @@ func NewRunner(options ...RunnerOption) (*LuaRunner, error) {
runner := &LuaRunner{
bufferSize: 10, // Default buffer size
requireCache: NewRequireCache(),
requireCfg: RequireConfig{
requireCfg: &RequireConfig{
LibDirs: []string{},
},
}
@ -61,7 +60,13 @@ func NewRunner(options ...RunnerOption) (*LuaRunner, error) {
runner.jobQueue = make(chan job, runner.bufferSize)
runner.isRunning.Store(true)
// Set up require functionality
// Create a shared config pointer that will be updated per request
runner.requireCfg = &RequireConfig{
ScriptDir: runner.scriptDir,
LibDirs: runner.libDirs,
}
// Set up require functionality ONCE
if err := SetupRequire(state, runner.requireCache, runner.requireCfg); err != nil {
state.Close()
return nil, ErrInitFailed
@ -226,14 +231,11 @@ func (r *LuaRunner) eventLoop() {
// executeJob runs a script in the sandbox environment
func (r *LuaRunner) executeJob(j job) JobResult {
// If the job has a script path, update the require context
// If the job has a script path, update paths without re-registering
if j.ScriptPath != "" {
// Update the script directory for require
scriptDir := filepath.Dir(j.ScriptPath)
r.requireCfg.ScriptDir = scriptDir
// Update in the require cache config
SetupRequire(r.state, r.requireCache, r.requireCfg)
r.mu.Lock()
UpdateRequirePaths(r.requireCfg, j.ScriptPath)
r.mu.Unlock()
}
// Re-run init function if needed

View File

@ -35,18 +35,18 @@ func NewRequireCache() *RequireCache {
}
// SetupRequire configures the Lua state with a secure require function
func SetupRequire(state *luajit.State, cache *RequireCache, config RequireConfig) error {
func SetupRequire(state *luajit.State, cache *RequireCache, config *RequireConfig) error {
// Register the loader function
err := state.RegisterGoFunction("__go_load_module", func(s *luajit.State) int {
// Get module name
modName := s.ToString(1)
if modName == "" {
s.PushString("module name required")
return -1 // Return error
return -1
}
// Try to load the module
bytecode, err := findAndCompileModule(s, cache, config, modName)
// Use the pointer to the shared config
bytecode, err := findAndCompileModule(s, cache, *config, modName)
if err != nil {
if err == ErrModuleNotFound {
s.PushString("module '" + modName + "' not found")
@ -114,6 +114,13 @@ func SetupRequire(state *luajit.State, cache *RequireCache, config RequireConfig
return state.DoString(setupScript)
}
// UpdateRequirePaths updates the require paths in the config without further allocations or re-registering the loader.
func UpdateRequirePaths(config *RequireConfig, scriptPath string) {
if scriptPath != "" {
config.ScriptDir = filepath.Dir(scriptPath)
}
}
// findAndCompileModule finds a module in allowed directories and compiles it to bytecode
func findAndCompileModule(
state *luajit.State,