Skip to content

PrettyPrinter is not threadsafe. #214

Closed
@EdgeCaseBerg

Description

@EdgeCaseBerg

The PrettyPrinter, according to the docs:

Class for pretty printing. After instantiating, you can use the format() and formatNode() methods to convert XML to a formatted string. The class can be reused to pretty print any number of XML nodes.

The last sentence about being able to print any number of xml nodes I took to mean that the class operates in a pure manner and I could use this a concurrent environment. That was probably a bad assumption on my part. But here's a test case to reproduce the problem:

import scala.concurrent._
import scala.xml._
import java.util.concurrent.CountDownLatch
import scala.concurrent.ExecutionContext.Implicits.global

val p = new PrettyPrinter(width = Int.MaxValue, step = 2)
def xmlNode() = <A><B><C>Hello</C><D>There</D></B></A>
val latch = new CountDownLatch(1)
 
val futurePretty = (0 to 10).map { _ =>
	Future {
		val x = xmlNode()
		latch.await()
		p.format(x)
	}
}

latch.countDown()

val l = Future.sequence(futurePretty)

l.value.map(println)

On a run on my machine I see the result of that last console command as:

scala> l.value.map(println)
Success(Vector(<A>
  <B>
  <B>
    <C>Hello</C>
    <C>Hello</C>
    <C>Hello</C>
    <D>There</D>
  </B>
    <D>There</D>
  </B></B>
    <D>There</D>
</A>, <A>
  <B>
  <B>
    <C>Hello</C>
    <C>Hello</C>
... snipped for brevity...

Which clearly indicates to me that the pretty printer is using some buffer internal to the instance and therefore calling .format from different threads causes this buffer to be filled with values from each calling thread. This jumbles things up a bit.

If it's unlikely that this issue will be fixed at any point, could we please update the documentation to leave an explicit note that the class is not thread safe and should not be used like that?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions