Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race Condition in vector_tile_worker_source #6308

Closed
samwyma opened this issue Mar 9, 2018 · 1 comment
Closed

Race Condition in vector_tile_worker_source #6308

samwyma opened this issue Mar 9, 2018 · 1 comment
Assignees
Labels

Comments

@samwyma
Copy link

samwyma commented Mar 9, 2018

mapbox-gl-js version: 0.44.1

Explanation

The reloadTile function in vector_tile_worker_source.js has a race condition, at least as far as I can tell. If three requests are placed to reloadTile, one after another, then if the third request is placed after the first has finished, but while the second is still processing, then the callback for the third request (i.e. the latest one) will never be called.

We're using the renderer of this project in a fork and the assumption we've made when using the worker thread is that the last request made to the worker will always resolve. Are we assuming correctly that this should be the case?

I'm pretty sure the fix for this is to change this line:
workerTile.reloadCallback = callback;
to this:
workerTile.reloadCallback = done.bind(workerTile);

But I'm not sure if the above would break anything in the wider codebase, since we're only using parts of the renderer.

Steps to Trigger Behavior

  1. Have relatively large tiles which take a non-trivial amount of time to parse
  2. Get them to parse frequently (e.g. by changing filters) and then stop and wait. Do this until the map hangs when rendering.

Expected Behavior

The map renders without timing out.

Actual Behavior

The rendering times out.

@jfirebaugh
Copy link
Contributor

Your analysis looks correct. To spell it out explicitly, since it took me a while to work out, suppose:

  1. reloadTile is called when the current status is done. workerTile.parse is passed the callback done.bind(workerTile). (done captures callback in its closure.) Parsing begins.
  2. reloadTile is called a second time. reloadCallback is set to callback.
  3. Parsing finishes and the bound done from step 1 is called. reloadCallback is set, so parse is called again with the callback from step 2.
  4. reloadTile is called a third time. reloadCallback is set to (the new) callback.
  5. Parsing triggered by step 3 completes, and calls the callback from step 2. This is just a regular callback, not a bound done, so the reloadCallback set in step 4 is left hanging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants