Fix race condition surrounding global orgWriter
Since writers are normally only used synchronously (i.e. to write one document at a time), we don't guard modifications to their internal state (e.g. temporarily replacing the string.Builder in WriteNodesAsString) against race conditions. The package global `orgWriter` and corresponding use cases of it (`org.String`, `$node.String`) break that pattern - the writer is potentially used from multiple go routines at the same time. This results in race conditions that manifest as error messages like e.g. could not write output: runtime error: invalid memory address or nil pointer dereference. Using unrendered content. Additionally, since we catch panics in `Document.Write`, the corresponding stack trace is lost and dependents of go-org never know what hit them. As using a writer across simultaneously across go routines is not a standard pattern, we'll sync the use of the global `orgWriter` instead of trying to make the actual writer threadsafe; less code noise for the common use case.
This commit is contained in:
parent
18314a9f41
commit
5464ab37d2
12 changed files with 41 additions and 35 deletions
|
@ -400,7 +400,7 @@ func isValidPostChar(r rune) bool {
|
|||
func isValidBorderChar(r rune) bool { return !unicode.IsSpace(r) }
|
||||
|
||||
func (l RegularLink) Kind() string {
|
||||
description := String(l.Description)
|
||||
description := String(l.Description...)
|
||||
descProtocol, descExt := strings.SplitN(description, ":", 2)[0], path.Ext(description)
|
||||
if ok := descProtocol == "file" || descProtocol == "http" || descProtocol == "https"; ok && imageExtensionRegexp.MatchString(descExt) {
|
||||
return "image"
|
||||
|
@ -420,14 +420,14 @@ func (l RegularLink) Kind() string {
|
|||
return "regular"
|
||||
}
|
||||
|
||||
func (n Text) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n LineBreak) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n ExplicitLineBreak) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n StatisticToken) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n Emphasis) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n InlineBlock) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n LatexFragment) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n FootnoteLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n RegularLink) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n Macro) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n Timestamp) String() string { return orgWriter.WriteNodesAsString(n) }
|
||||
func (n Text) String() string { return String(n) }
|
||||
func (n LineBreak) String() string { return String(n) }
|
||||
func (n ExplicitLineBreak) String() string { return String(n) }
|
||||
func (n StatisticToken) String() string { return String(n) }
|
||||
func (n Emphasis) String() string { return String(n) }
|
||||
func (n InlineBlock) String() string { return String(n) }
|
||||
func (n LatexFragment) String() string { return String(n) }
|
||||
func (n FootnoteLink) String() string { return String(n) }
|
||||
func (n RegularLink) String() string { return String(n) }
|
||||
func (n Macro) String() string { return String(n) }
|
||||
func (n Timestamp) String() string { return String(n) }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue