Skip to content

Commit cc639fb

Browse files
committed
Fix capture of worker variable in allocateUnusedWorkers
1 parent ef3e423 commit cc639fb

File tree

1 file changed

+100
-97
lines changed

1 file changed

+100
-97
lines changed

src/library_pthread.js

Lines changed: 100 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -252,112 +252,115 @@ var LibraryPThread = {
252252
Module['print']('Preallocating ' + numWorkers + ' workers for a pthread spawn pool.');
253253

254254
var numWorkersLoaded = 0;
255+
var pthreadMainJs = 'pthread-main.js';
256+
// Allow HTML module to configure the location where the 'pthread-main.js' file will be loaded from,
257+
// either via Module.locateFile() function, or via Module.pthreadMainPrefixURL string. If neither
258+
// of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
259+
if (typeof Module['locateFile'] === 'function') pthreadMainJs = Module['locateFile'](pthreadMainJs);
260+
else if (Module['pthreadMainPrefixURL']) pthreadMainJs = Module['pthreadMainPrefixURL'] + pthreadMainJs;
261+
255262
for (var i = 0; i < numWorkers; ++i) {
256-
var pthreadMainJs = 'pthread-main.js';
257-
// Allow HTML module to configure the location where the 'pthread-main.js' file will be loaded from,
258-
// either via Module.locateFile() function, or via Module.pthreadMainPrefixURL string. If neither
259-
// of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
260-
if (typeof Module['locateFile'] === 'function') pthreadMainJs = Module['locateFile'](pthreadMainJs);
261-
else if (Module['pthreadMainPrefixURL']) pthreadMainJs = Module['pthreadMainPrefixURL'] + pthreadMainJs;
262263
var worker = new Worker(pthreadMainJs);
263264

264-
worker.onmessage = function(e) {
265-
var d = e.data;
266-
// TODO: Move the proxied call mechanism into a queue inside heap.
267-
if (d.proxiedCall) {
268-
var returnValue;
269-
var funcTable = (d.func >= 0) ? proxiedFunctionTable : ASM_CONSTS;
270-
var funcIdx = (d.func >= 0) ? d.func : (-1 - d.func);
271-
PThread.currentProxiedOperationCallerThread = worker.pthread.threadInfoStruct; // Sometimes we need to backproxy events to the calling thread (e.g. HTML5 DOM events handlers such as emscripten_set_mousemove_callback()), so keep track in a globally accessible variable about the thread that initiated the proxying.
272-
switch(d.proxiedCall & 31) {
273-
case 1: returnValue = funcTable[funcIdx](); break;
274-
case 2: returnValue = funcTable[funcIdx](d.p0); break;
275-
case 3: returnValue = funcTable[funcIdx](d.p0, d.p1); break;
276-
case 4: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2); break;
277-
case 5: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3); break;
278-
case 6: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4); break;
279-
case 7: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5); break;
280-
case 8: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6); break;
281-
case 9: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6, d.p7); break;
282-
case 10: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6, d.p7, d.p8); break;
283-
default:
284-
if (d.proxiedCall) {
285-
Module['printErr']("worker sent an unknown proxied call idx " + d.proxiedCall);
286-
console.error(e.data);
287-
}
288-
break;
289-
}
290-
if (d.returnValue) {
291-
if (d.proxiedCall < 32) HEAP32[d.returnValue >> 2] = returnValue;
292-
else HEAPF64[d.returnValue >> 3] = returnValue;
293-
}
294-
var waitAddress = d.waitAddress;
295-
if (waitAddress) {
296-
Atomics.store(HEAP32, waitAddress >> 2, 1);
297-
Atomics.wake(HEAP32, waitAddress >> 2, 1);
265+
(function(worker) {
266+
worker.onmessage = function(e) {
267+
var d = e.data;
268+
// TODO: Move the proxied call mechanism into a queue inside heap.
269+
if (d.proxiedCall) {
270+
var returnValue;
271+
var funcTable = (d.func >= 0) ? proxiedFunctionTable : ASM_CONSTS;
272+
var funcIdx = (d.func >= 0) ? d.func : (-1 - d.func);
273+
PThread.currentProxiedOperationCallerThread = worker.pthread.threadInfoStruct; // Sometimes we need to backproxy events to the calling thread (e.g. HTML5 DOM events handlers such as emscripten_set_mousemove_callback()), so keep track in a globally accessible variable about the thread that initiated the proxying.
274+
switch(d.proxiedCall & 31) {
275+
case 1: returnValue = funcTable[funcIdx](); break;
276+
case 2: returnValue = funcTable[funcIdx](d.p0); break;
277+
case 3: returnValue = funcTable[funcIdx](d.p0, d.p1); break;
278+
case 4: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2); break;
279+
case 5: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3); break;
280+
case 6: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4); break;
281+
case 7: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5); break;
282+
case 8: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6); break;
283+
case 9: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6, d.p7); break;
284+
case 10: returnValue = funcTable[funcIdx](d.p0, d.p1, d.p2, d.p3, d.p4, d.p5, d.p6, d.p7, d.p8); break;
285+
default:
286+
if (d.proxiedCall) {
287+
Module['printErr']("worker sent an unknown proxied call idx " + d.proxiedCall);
288+
console.error(e.data);
289+
}
290+
break;
291+
}
292+
if (d.returnValue) {
293+
if (d.proxiedCall < 32) HEAP32[d.returnValue >> 2] = returnValue;
294+
else HEAPF64[d.returnValue >> 3] = returnValue;
295+
}
296+
var waitAddress = d.waitAddress;
297+
if (waitAddress) {
298+
Atomics.store(HEAP32, waitAddress >> 2, 1);
299+
Atomics.wake(HEAP32, waitAddress >> 2, 1);
300+
}
301+
return;
298302
}
299-
return;
300-
}
301303

302-
// If this message is intended to a recipient that is not the main thread, forward it to the target thread.
303-
if (d.targetThread && d.targetThread != _pthread_self()) {
304-
var thread = PThread.pthreads[d.targetThread];
305-
if (thread) {
306-
thread.worker.postMessage(e.data, d.transferList);
307-
} else {
308-
console.error('Internal error! Worker sent a message "' + d.cmd + '" to target pthread ' + d.targetThread + ', but that thread no longer exists!');
304+
// If this message is intended to a recipient that is not the main thread, forward it to the target thread.
305+
if (d.targetThread && d.targetThread != _pthread_self()) {
306+
var thread = PThread.pthreads[d.targetThread];
307+
if (thread) {
308+
thread.worker.postMessage(e.data, d.transferList);
309+
} else {
310+
console.error('Internal error! Worker sent a message "' + d.cmd + '" to target pthread ' + d.targetThread + ', but that thread no longer exists!');
311+
}
312+
return;
309313
}
310-
return;
311-
}
312314

313-
if (d.cmd === 'processQueuedMainThreadWork') {
314-
// TODO: Must post message to main Emscripten thread in PROXY_TO_WORKER mode.
315-
_emscripten_main_thread_process_queued_calls();
316-
} else if (d.cmd === 'spawnThread') {
317-
__spawn_thread(e.data);
318-
} else if (d.cmd === 'cleanupThread') {
319-
__cleanup_thread(d.thread);
320-
} else if (d.cmd === 'killThread') {
321-
__kill_thread(d.thread);
322-
} else if (d.cmd === 'cancelThread') {
323-
__cancel_thread(d.thread);
324-
} else if (d.cmd === 'loaded') {
325-
worker.loaded = true;
326-
// If this Worker is already pending to start running a thread, launch the thread now
327-
if (worker.runPthread) {
328-
worker.runPthread();
329-
delete worker.runPthread;
330-
}
331-
++numWorkersLoaded;
332-
if (numWorkersLoaded === numWorkers && onFinishedLoading) {
333-
onFinishedLoading();
315+
if (d.cmd === 'processQueuedMainThreadWork') {
316+
// TODO: Must post message to main Emscripten thread in PROXY_TO_WORKER mode.
317+
_emscripten_main_thread_process_queued_calls();
318+
} else if (d.cmd === 'spawnThread') {
319+
__spawn_thread(e.data);
320+
} else if (d.cmd === 'cleanupThread') {
321+
__cleanup_thread(d.thread);
322+
} else if (d.cmd === 'killThread') {
323+
__kill_thread(d.thread);
324+
} else if (d.cmd === 'cancelThread') {
325+
__cancel_thread(d.thread);
326+
} else if (d.cmd === 'loaded') {
327+
worker.loaded = true;
328+
// If this Worker is already pending to start running a thread, launch the thread now
329+
if (worker.runPthread) {
330+
worker.runPthread();
331+
delete worker.runPthread;
332+
}
333+
++numWorkersLoaded;
334+
if (numWorkersLoaded === numWorkers && onFinishedLoading) {
335+
onFinishedLoading();
336+
}
337+
} else if (d.cmd === 'print') {
338+
Module['print']('Thread ' + d.threadId + ': ' + d.text);
339+
} else if (d.cmd === 'printErr') {
340+
Module['printErr']('Thread ' + d.threadId + ': ' + d.text);
341+
} else if (d.cmd === 'alert') {
342+
alert('Thread ' + d.threadId + ': ' + d.text);
343+
} else if (d.cmd === 'exit') {
344+
// currently no-op
345+
} else if (d.cmd === 'cancelDone') {
346+
PThread.freeThreadData(worker.pthread);
347+
worker.pthread = undefined; // Detach the worker from the pthread object, and return it to the worker pool as an unused worker.
348+
PThread.unusedWorkerPool.push(worker);
349+
// TODO: Free if detached.
350+
PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker.pthread), 1); // Not a running Worker anymore.
351+
} else if (d.cmd === 'objectTransfer') {
352+
PThread.receiveObjectTransfer(e.data);
353+
} else if (e.data.target === 'setimmediate') {
354+
worker.postMessage(e.data); // Worker wants to postMessage() to itself to implement setImmediate() emulation.
355+
} else {
356+
Module['printErr']("worker sent an unknown command " + d.cmd);
334357
}
335-
} else if (d.cmd === 'print') {
336-
Module['print']('Thread ' + d.threadId + ': ' + d.text);
337-
} else if (d.cmd === 'printErr') {
338-
Module['printErr']('Thread ' + d.threadId + ': ' + d.text);
339-
} else if (d.cmd === 'alert') {
340-
alert('Thread ' + d.threadId + ': ' + d.text);
341-
} else if (d.cmd === 'exit') {
342-
// currently no-op
343-
} else if (d.cmd === 'cancelDone') {
344-
PThread.freeThreadData(worker.pthread);
345-
worker.pthread = undefined; // Detach the worker from the pthread object, and return it to the worker pool as an unused worker.
346-
PThread.unusedWorkerPool.push(worker);
347-
// TODO: Free if detached.
348-
PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker.pthread), 1); // Not a running Worker anymore.
349-
} else if (d.cmd === 'objectTransfer') {
350-
PThread.receiveObjectTransfer(e.data);
351-
} else if (e.data.target === 'setimmediate') {
352-
worker.postMessage(e.data); // Worker wants to postMessage() to itself to implement setImmediate() emulation.
353-
} else {
354-
Module['printErr']("worker sent an unknown command " + d.cmd);
355-
}
356-
};
358+
};
357359

358-
worker.onerror = function(e) {
359-
Module['printErr']('pthread sent an error! ' + e.filename + ':' + e.lineno + ': ' + e.message);
360-
};
360+
worker.onerror = function(e) {
361+
Module['printErr']('pthread sent an error! ' + e.filename + ':' + e.lineno + ': ' + e.message);
362+
};
363+
}(worker));
361364

362365
// Allocate tempDoublePtr for the worker. This is done here on the worker's behalf, since we may need to do this statically
363366
// if the runtime has not been loaded yet, etc. - so we just use getMemory, which is main-thread only.

0 commit comments

Comments
 (0)