ref: ea391fd0eead3ce2ccbfe6594dfc9cf1c6e02b92
parent: 793e9a1d7c697af189320c9e684e5559bb06e3c1
author: Philip Silva <philip.silva@protonmail.com>
date: Tue Jun 1 16:23:02 EDT 2021
Make fs package more thread safe
--- a/browser/fs/fs.go
+++ b/browser/fs/fs.go
@@ -11,7 +11,7 @@
var (
log *logger.Logger
- mu sync.Mutex
+ mu sync.RWMutex
oFS *fs.FS
un string
gn string
@@ -23,49 +23,26 @@
log = l
}
-func Update(htm string, js []string) {
- mu.Lock()
- defer mu.Unlock()
-
- html = htm
-
- for name := range jsDir.Children() {
- jsDir.DeleteChild(name)
- }
- for i, s := range js {
- fn := fmt.Sprintf("%d.js", i)
- f := fs.NewStaticFile(
- oFS.NewStat(fn, un, gn, 0400),
- []byte(s),
- )
- jsDir.AddChild(f)
- }
-}
-
-func Srv9p() {
- if err := srv9p(); err != nil {
- log.Errorf("srv9p: %v", err)
- }
-}
-
-func srv9p() (err error) {
+func init() {
var root *fs.StaticDir
u, err := user.Current()
if err != nil {
- return fmt.Errorf("get user: %w", err)
+ log.Errorf("get user: %w", err)
+ return
}
un = u.Username
gn, err = group(u)
if err != nil {
- return fmt.Errorf("get group: %w", err)
+ log.Errorf("get group: %w", err)
+ return
}
oFS, root = fs.NewFS(un, gn, 0500)
h := fs.NewDynamicFile(
oFS.NewStat("html", un, gn, 0400),
func() []byte {
- mu.Lock()
- defer mu.Unlock()
+ mu.RLock()
+ defer mu.RUnlock()
return []byte(html)
},
@@ -73,10 +50,34 @@
root.AddChild(h)
d, err := fs.CreateStaticDir(oFS, root, un, "js", 0500|proto.DMDIR, 0)
if err != nil {
+ log.Errorf("create static dir: %w", err)
return
}
jsDir = d.(*fs.StaticDir)
root.AddChild(jsDir)
+}
- return post(oFS.Server())
+func Update(htm string, js []string) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ html = htm
+
+ for name := range jsDir.Children() {
+ jsDir.DeleteChild(name)
+ }
+ for i, s := range js {
+ fn := fmt.Sprintf("%d.js", i)
+ f := fs.NewStaticFile(
+ oFS.NewStat(fn, un, gn, 0400),
+ []byte(s),
+ )
+ jsDir.AddChild(f)
+ }
+}
+
+func Srv9p() {
+ if err := post(oFS.Server()); err != nil {
+ log.Errorf("srv9p: %v", err)
+ }
}
--- a/browser/website.go
+++ b/browser/website.go
@@ -12,7 +12,6 @@
"github.com/psilva261/opossum/nodes"
"github.com/psilva261/opossum/style"
"strings"
- "sync"
)
const (
@@ -24,26 +23,8 @@
duit.UI
opossum.ContentType
d *domino.Domino
-
- mu sync.Mutex
- html string
- js []string
}
-func (w *Website) Html() string {
- w.mu.Lock()
- defer w.mu.Unlock()
-
- return w.html
-}
-
-func (w *Website) Js() []string {
- w.mu.Lock()
- defer w.mu.Unlock()
-
- return append([]string{}, w.js...)
-}
-
func (w *Website) layout(f opossum.Fetcher, htm string, layouting int) {
defer func() {
browser.statusBarMsg("", false)
@@ -99,6 +80,7 @@
// 3rd pass is only needed initially to load the scripts and set the goja VM
// state. During subsequent calls from click handlers that state is kept.
+ var js []string
if *ExperimentalJsInsecure && layouting != ClickRelayout {
log.Printf("3rd pass")
nt := nodes.NewNodeTree(doc, style.Map{}, nodeMap, nil)
@@ -118,10 +100,7 @@
}
downloads[src] = string(buf)
}
- codes := domino.Scripts(nt, downloads)
- w.mu.Lock()
- w.js = append([]string{}, codes...)
- w.mu.Unlock()
+ js = domino.Scripts(nt, downloads)
log.Infof("JS pipeline start")
if w.d != nil {
log.Infof("Stop existing JS instance")
@@ -129,7 +108,7 @@
}
w.d = domino.NewDomino(htm, browser, nt)
w.d.Start()
- jsProcessed, changed, err := processJS2(w.d, codes)
+ jsProcessed, changed, err := processJS2(w.d, js)
if changed && err == nil {
htm = jsProcessed
if debugPrintHtml {
@@ -171,10 +150,7 @@
w.UI = scroller
}
- w.mu.Lock()
- w.html = htm
- w.mu.Unlock()
- fs.Update(w.html, w.js)
+ fs.Update(htm, js)
log.Flush()
}