Spaces:
Configuration error
Configuration error
package library | |
import ( | |
"errors" | |
"fmt" | |
"os" | |
"path/filepath" | |
"runtime" | |
"github.com/rs/zerolog/log" | |
) | |
/* | |
This file contains functions to load libraries from the asset directory to keep the business logic clean. | |
*/ | |
// skipLibraryPath checks if LOCALAI_SKIP_LIBRARY_PATH is set | |
var skipLibraryPath = os.Getenv("LOCALAI_SKIP_LIBRARY_PATH") != "" | |
// LoadExtractedLibs loads the extracted libraries from the asset dir | |
func LoadExtractedLibs(dir string) error { | |
// Skip this if LOCALAI_SKIP_LIBRARY_PATH is set | |
if skipLibraryPath { | |
return nil | |
} | |
var err error = nil | |
for _, libDir := range []string{filepath.Join(dir, "backend-assets", "lib"), filepath.Join(dir, "lib")} { | |
err = errors.Join(err, LoadExternal(libDir)) | |
} | |
return err | |
} | |
// LoadLDSO checks if there is a ld.so in the asset dir and if so, prefixes the grpc process with it. | |
// In linux, if we find a ld.so in the asset dir we prefix it to run with the libs exposed in | |
// LD_LIBRARY_PATH for more compatibility | |
// If we don't do this, we might run into stack smash | |
// See also: https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229 | |
// In this case, we expect a ld.so in the lib asset dir. | |
// If that's present, we use it to run the grpc backends as supposedly built against | |
// that specific version of ld.so | |
func LoadLDSO(assetDir string, args []string, grpcProcess string) ([]string, string) { | |
if skipLibraryPath { | |
return args, grpcProcess | |
} | |
if runtime.GOOS != "linux" { | |
return args, grpcProcess | |
} | |
// Check if there is a ld.so file in the assetDir, if it does, we need to run the grpc process with it | |
ldPath := filepath.Join(assetDir, "backend-assets", "lib", "ld.so") | |
if _, err := os.Stat(ldPath); err == nil { | |
log.Debug().Msgf("ld.so found") | |
// We need to run the grpc process with the ld.so | |
args = append([]string{grpcProcess}, args...) | |
grpcProcess = ldPath | |
} | |
return args, grpcProcess | |
} | |
// LoadExternal sets the LD_LIBRARY_PATH to include the given directory | |
func LoadExternal(dir string) error { | |
// Skip this if LOCALAI_SKIP_LIBRARY_PATH is set | |
if skipLibraryPath { | |
return nil | |
} | |
lpathVar := "LD_LIBRARY_PATH" | |
if runtime.GOOS == "darwin" { | |
lpathVar = "DYLD_FALLBACK_LIBRARY_PATH" // should it be DYLD_LIBRARY_PATH ? | |
} | |
var setErr error = nil | |
if _, err := os.Stat(dir); err == nil { | |
ldLibraryPath := os.Getenv(lpathVar) | |
if ldLibraryPath == "" { | |
ldLibraryPath = dir | |
} else { | |
ldLibraryPath = fmt.Sprintf("%s:%s", ldLibraryPath, dir) | |
} | |
setErr = errors.Join(setErr, os.Setenv(lpathVar, ldLibraryPath)) | |
} | |
return setErr | |
} | |