[ 
https://issues.apache.org/jira/browse/SPARK-13747?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16001365#comment-16001365
 ] 

Shixiong Zhu commented on SPARK-13747:
--------------------------------------

[~mousa] This is is because Spark uses ThreadLocal in a fork-join pool. Let me 
try to clarify the issue.

A fork-join pool allows to run another pending task in the same thread when a 
running task is calling Await.ready/result. The magic is when someone calls 
Await.ready/result, it will first check if there is any pending task submitted 
to the pool, if so, it will call the pending task instead of waiting. (See 
scala.concurrent#blocking)

In Spark, the codes hitting this issue have the following pattern.

{code}
try {
    check if a thread local is set
    if so, throw an exception
    else
        set the thread local value
        do some work
        Call Await.ready/result to wait for a result // This doesn't clear the 
thread local value. 
                                                     // If the fork-join pool 
schedules a pending task here,
                                                     // it will see the thread 
local value.
        do some work
} finally {
    clear the thread local value.
}
{code}

My PR is basically just not calling `scala.concurrent#blocking`. It just makes 
a fork-join pool become a normal thread pool executor.


> Concurrent execution in SQL doesn't work with Scala ForkJoinPool
> ----------------------------------------------------------------
>
>                 Key: SPARK-13747
>                 URL: https://issues.apache.org/jira/browse/SPARK-13747
>             Project: Spark
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 2.0.0, 2.0.1
>            Reporter: Shixiong Zhu
>            Assignee: Shixiong Zhu
>
> Run the following codes may fail
> {code}
> (1 to 100).par.foreach { _ =>
>   println(sc.parallelize(1 to 5).map { i => (i, i) }.toDF("a", "b").count())
> }
> java.lang.IllegalArgumentException: spark.sql.execution.id is already set 
>         at 
> org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:87)
>  
>         at 
> org.apache.spark.sql.DataFrame.withNewExecutionId(DataFrame.scala:1904) 
>         at org.apache.spark.sql.DataFrame.collect(DataFrame.scala:1385) 
> {code}
> This is because SparkContext.runJob can be suspended when using a 
> ForkJoinPool (e.g.,scala.concurrent.ExecutionContext.Implicits.global) as it 
> calls Await.ready (introduced by https://github.com/apache/spark/pull/9264).
> So when SparkContext.runJob is suspended, ForkJoinPool will run another task 
> in the same thread, however, the local properties has been polluted.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to