@@ -22,9 +22,15 @@ import kotlin.coroutines.experimental.CoroutineContext
2222
2323/* *
2424 * Represents common pool of shared threads as coroutine dispatcher for compute-intensive tasks.
25- * It uses [java.util.concurrent.ForkJoinPool] when available, which implements efficient work-stealing algorithm for its queues, so every
26- * coroutine resumption is dispatched as a separate task even when it already executes inside the pool.
27- * When available, it wraps `ForkJoinPool.commonPool` and provides a similar shared pool where not.
25+ *
26+ * If there isn't a SecurityManager present it uses [java.util.concurrent.ForkJoinPool] when available, which implements
27+ * efficient work-stealing algorithm for its queues, so every coroutine resumption is dispatched as a separate task even
28+ * when it already executes inside the pool. When available, it wraps `ForkJoinPool.commonPool` and provides a similar
29+ * shared pool where not.
30+ *
31+ * If there is a SecurityManager present (as would be if running inside a Java Web Start context) then a plain thread
32+ * pool is created. This is to work around the fact that ForkJoinPool creates threads that cannot perform
33+ * privileged actions.
2834 */
2935object CommonPool : CoroutineDispatcher() {
3036 private var usePrivatePool = false
@@ -35,6 +41,7 @@ object CommonPool : CoroutineDispatcher() {
3541 private inline fun <T > Try (block : () -> T ) = try { block() } catch (e: Throwable ) { null }
3642
3743 private fun createPool (): ExecutorService {
44+ if (System .getSecurityManager() != null ) return createPlainPool()
3845 val fjpClass = Try { Class .forName(" java.util.concurrent.ForkJoinPool" ) }
3946 ? : return createPlainPool()
4047 if (! usePrivatePool) {
0 commit comments