Skip to content

Commit

Permalink
[feature/OFFICIALLY UNSUPPORTED] add nowasm build tag to disable buil…
Browse files Browse the repository at this point in the history
…ding with WebAssembly (#3429)

* add experimental build-tag 'nowasm' which uses local ffmpeg / ffprobe

* updated experimental support message

* add comment to build script explaining build tag

* add nowasm build tags to moderncsqlite files
  • Loading branch information
NyaaaWhatsUpDoc authored Oct 14, 2024
1 parent 157ee31 commit 6a76b9d
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 26 deletions.
2 changes: 1 addition & 1 deletion internal/db/sqlite/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !moderncsqlite3
//go:build !moderncsqlite3 && !nowasm

package sqlite

Expand Down
2 changes: 1 addition & 1 deletion internal/db/sqlite/driver_moderncsqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build moderncsqlite3
//go:build moderncsqlite3 || nowasm

package sqlite

Expand Down
2 changes: 1 addition & 1 deletion internal/db/sqlite/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !moderncsqlite3
//go:build !moderncsqlite3 && !nowasm

package sqlite

Expand Down
2 changes: 1 addition & 1 deletion internal/db/sqlite/errors_moderncsqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build moderncsqlite3
//go:build moderncsqlite3 || nowasm

package sqlite

Expand Down
28 changes: 28 additions & 0 deletions internal/media/ffmpeg/args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package ffmpeg

import (
"codeberg.org/gruf/go-ffmpreg/wasm"
)

// Args encapsulates the passing of common
// configuration options to run an instance
// of a compiled WebAssembly module that is
// run in a typical CLI manner.
type Args = wasm.Args
142 changes: 142 additions & 0 deletions internal/media/ffmpeg/exec_nowasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build nowasm

package ffmpeg

import (
"context"
"fmt"
"io"
"io/fs"
"os/exec"

"codeberg.org/gruf/go-ffmpreg/wasm"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/sys"
)

func init() {
fmt.Println("!! you are using an unsupported build configuration of gotosocial with WebAssembly disabled !!")
fmt.Println("!! please do not file bug reports regarding media processing with this configuration !!")
fmt.Println("!! it is also less secure; this does not enforce version checks on ffmpeg / ffprobe versions !!")
}

// runCmd will run 'name' with the given arguments, returning exit code or error.
func runCmd(ctx context.Context, name string, args wasm.Args) (uint32, error) {
cmd := exec.CommandContext(ctx, name, args.Args...) //nolint:gosec

// Set provided std files.
cmd.Stdin = args.Stdin
cmd.Stdout = args.Stdout
cmd.Stderr = args.Stderr

if args.Config != nil {
// Gather some information
// from module config func.
var cfg falseModuleConfig
_ = args.Config(&cfg)

// Extract from conf.
cmd.Env = cfg.env
}

// Run prepared command, catching err type.
switch err := cmd.Run(); err := err.(type) {

// Extract code from
// any exit error type.
case *exec.ExitError:
rc := err.ExitCode()
return uint32(rc), err

default:
return 0, err
}
}

type falseModuleConfig struct{ env []string }

func (cfg *falseModuleConfig) WithArgs(...string) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithEnv(key string, value string) wazero.ModuleConfig {
cfg.env = append(cfg.env, key+"="+value)
return cfg // noop
}

func (cfg *falseModuleConfig) WithFS(fs.FS) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithFSConfig(wazero.FSConfig) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithName(string) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithStartFunctions(...string) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithStderr(io.Writer) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithStdin(io.Reader) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithStdout(io.Writer) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithWalltime(sys.Walltime, sys.ClockResolution) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithSysWalltime() wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithNanotime(sys.Nanotime, sys.ClockResolution) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithSysNanotime() wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithNanosleep(sys.Nanosleep) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithOsyield(sys.Osyield) wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithSysNanosleep() wazero.ModuleConfig {
return cfg // noop
}

func (cfg *falseModuleConfig) WithRandSource(io.Reader) wazero.ModuleConfig {
return cfg // noop
}
8 changes: 7 additions & 1 deletion internal/media/ffmpeg/ffmpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !nowasm

package ffmpeg

import (
"context"

"codeberg.org/gruf/go-ffmpreg/wasm"
)

// ffmpegRunner limits the number of
Expand All @@ -36,5 +40,7 @@ func InitFfmpeg(ctx context.Context, max int) error {

// Ffmpeg runs the given arguments with an instance of ffmpeg.
func Ffmpeg(ctx context.Context, args Args) (uint32, error) {
return ffmpegRunner.Run(ctx, ffmpeg, args)
return ffmpegRunner.Run(ctx, func() (uint32, error) {
return wasm.Run(ctx, runtime, ffmpeg, args)
})
}
49 changes: 49 additions & 0 deletions internal/media/ffmpeg/ffmpeg_nowasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build nowasm

package ffmpeg

import (
"context"
"os/exec"
)

// ffmpegRunner limits the number of
// ffmpeg WebAssembly instances that
// may be concurrently running, in
// order to reduce memory usage.
var ffmpegRunner runner

// InitFfmpeg looks for a local copy of ffmpeg in path, and prepares
// the runner to only allow max given concurrent running instances.
func InitFfmpeg(ctx context.Context, max int) error {
_, err := exec.LookPath("ffmpeg")
if err != nil {
return err
}
ffmpegRunner.Init(max)
return nil
}

// Ffmpeg runs the given arguments with an instance of ffmpeg.
func Ffmpeg(ctx context.Context, args Args) (uint32, error) {
return ffmpegRunner.Run(ctx, func() (uint32, error) {
return runCmd(ctx, "ffmpeg", args)
})
}
8 changes: 7 additions & 1 deletion internal/media/ffmpeg/ffprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !nowasm

package ffmpeg

import (
"context"

"codeberg.org/gruf/go-ffmpreg/wasm"
)

// ffprobeRunner limits the number of
Expand All @@ -36,5 +40,7 @@ func InitFfprobe(ctx context.Context, max int) error {

// Ffprobe runs the given arguments with an instance of ffprobe.
func Ffprobe(ctx context.Context, args Args) (uint32, error) {
return ffprobeRunner.Run(ctx, ffprobe, args)
return ffmpegRunner.Run(ctx, func() (uint32, error) {
return wasm.Run(ctx, runtime, ffprobe, args)
})
}
49 changes: 49 additions & 0 deletions internal/media/ffmpeg/ffprobe_nowasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build nowasm

package ffmpeg

import (
"context"
"os/exec"
)

// ffprobeRunner limits the number of
// ffprobe WebAssembly instances that
// may be concurrently running, in
// order to reduce memory usage.
var ffprobeRunner runner

// InitFfprobe looks for a local copy of ffprobe in path, and prepares
// the runner to only allow max given concurrent running instances.
func InitFfprobe(ctx context.Context, max int) error {
_, err := exec.LookPath("ffprobe")
if err != nil {
return err
}
ffprobeRunner.Init(max)
return nil
}

// Ffprobe runs the given arguments with an instance of ffprobe.
func Ffprobe(ctx context.Context, args Args) (uint32, error) {
return ffprobeRunner.Run(ctx, func() (uint32, error) {
return runCmd(ctx, "ffprobe", args)
})
}
9 changes: 3 additions & 6 deletions internal/media/ffmpeg/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ package ffmpeg

import (
"context"

"codeberg.org/gruf/go-ffmpreg/wasm"
"github.com/tetratelabs/wazero"
)

// runner simply abstracts away the complexities
Expand Down Expand Up @@ -53,7 +50,7 @@ func (r *runner) Init(n int) {

// Run will attempt to pass the given compiled WebAssembly module with args to run(), waiting on
// the receiving runner until a free slot is available to run an instance, (if a limit is enabled).
func (r *runner) Run(ctx context.Context, cmod wazero.CompiledModule, args Args) (uint32, error) {
func (r *runner) Run(ctx context.Context, run func() (uint32, error)) (uint32, error) {
select {
// Context canceled.
case <-ctx.Done():
Expand All @@ -66,6 +63,6 @@ func (r *runner) Run(ctx context.Context, cmod wazero.CompiledModule, args Args)
// Release slot back to pool on end.
defer func() { r.pool <- struct{}{} }()

// Pass to main module runner function.
return wasm.Run(ctx, runtime, cmod, args)
// Call run.
return run()
}
Loading

0 comments on commit 6a76b9d

Please sign in to comment.