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

setup runs twice in instance mode in the presence of p5.sound and large browser extensions #4669

Closed
1 task done
akshay-99 opened this issue Jul 2, 2020 · 6 comments · Fixed by #4726
Closed
1 task done
Assignees
Labels

Comments

@akshay-99
Copy link
Member

akshay-99 commented Jul 2, 2020

Most appropriate sub-area of p5.js?

  • Core/Environment/Rendering ( Initialization )

Details about the bug:

  • p5.js version: 1.0.0
  • Web browser and version: Chrome 79.0.3945.88
  • Operating System: Ubuntu 18.04
  • Steps to reproduce this:

Please bear with me this is going to be a large description 😅 .
TL;DR is that there apparently seems to be some kind of a race condition with the initialization in instance mode when p5 is run alongside p5.sound library and in the presence of some large extension like Grammarly.
This could also happen with other p5 libraries and with other large browser extensions.

let x = 0;
let sketch = function(p) {
  p.setup = function() {
    x =1;
  }; 
  p.draw = function() {
    console.log(x);
  }
};
let mp5 = new p5(sketch);

I would expect to see the value 1 repeatedly printed on my console. Which is what it does in Incognito mode or with Grammarly disabled. But when Grammarly is present, I get 2 . This would mean that the setup function is running twice.
image

Interestingly for this sketch,

let sketch = function(p) {
  p.setup = function() {
    throw new Error();
  };
};
let mp5 = new p5(sketch);

I get two errors on the console.

image
The stack traces of the errors are different though they happen on the same line.

I did a little digging. Here's what I found:
In both stack traces, the setup function is called from runIfPreloadsAreDone, which can be either called from _start or _decrementPreload. runIfPreloadsAreDone checks the value of context._preloadCount and if it is 0, it runs the setup function. _incrementPreload increases the value of _preloadCount by 1, whereas _decrementPreload decreases it by 1.
The _start function is called when the window load event fires. So with this I ran the debugger and here is the order of execution I found in my normal browser window ( with extensions enabled )

  1. _incrementPreload ( called from p5.sound.js ) preloadCount becomes 1
  2. _decrementPreload ( called from p5.sound.js ) preloadCount becomes 0
  3. runIfPreloadsAreDone ( called from _decrementPreload )
  4. setup ( as preloadCount was 0 )
  5. Window load event happens
  6. _start ( was listening for the window load event )
  7. runIfPreloadsAreDone ( called from _start )
  8. setup (called for the second time :( ) ( as preloadCount was 0 )

Here's the flow when extensions are disabled:

  1. _incrementPreload ( called from p5.sound.js ) preloadCount becomes 1
  2. Window load event happens (happens early probably because no large extensions to wait for)
  3. _start ( was listening for the window load event )
  4. runIfPreloadsAreDone ( called from _start ) (setup does not run as preloadCount is 1)
  5. _decrementPreload ( called from p5.sound.js ) preloadCount becomes 0
  6. runIfPreloadsAreDone ( called from _decrementPreload )
  7. setup ( as preloadCount was 0 ) ( setup runs only once, as it should )

I tried this in firefox (doesn't have any extensions installed) and while running normally I get the stacktrace of the second error, but it turns out I can actually make it switch to the first error's stack trace if I just wait for a while in the debugger.

I don't know if this is a problem with p5 or p5.sound or with Grammarly. I think it is a race condition with p5 which can be solved somehow. This is kind of a tricky bug which may be hard to reproduce but can give some really unexpected results for some users if they have extensions enabled. If someone else can take a look , please do.

EDIT: If it is confirmed that this actually is a bug, the fix can be quite easy perhaps by using _setupDone or something as a mutex lock.

@akshay-99 akshay-99 added the Bug label Jul 2, 2020
@limzykenneth
Copy link
Member

Does sound like a race condition bug in p5.js. I don't have the time to replicate this but if someone else can have a go at it and able to replicate it, you can go ahead with a fix.

@stalgiag
Copy link
Contributor

stalgiag commented Jul 3, 2020

I am able to reproduce with:

  • Mac 10.15.5
  • Chrome 83.0.4103.116
  • Grammarly Extension 14.960.0
  • and latest p5.sound

@tobidot
Copy link

tobidot commented Sep 6, 2020

Had the same issue, took me a while to even consider that
p5.setup might have been called twice.
So i just test now if setup has already been executed and skip it.

@Hsad1644
Copy link

its happening again :(

  • on Microsoft Edge Version 91.0.864.67 (Official build) (64-bit)
  • using p5.js 1.4.0 from jsdelivr.net

@kjprice
Copy link

kjprice commented Jun 7, 2023

I don't love this, but for now I'm having to remove the second p5 instance.

I'm using react-p5 version 1.3.35 but it seems to be the same for vanilla js.

Here's code:

For vanilla javascript:

let started = false;
let sketch = function(p) {
  p.setup = function() {
    if (started) {
      p5.remove();
    }
    started = true;
  }; 
};

For npm react:

let started = false;

export default (props) => {
  const setup = (p5, canvasParentRef) => {
    if (started) {
      p5.remove();
      return;
    }
    started = true;
    p5.createCanvas(500, 500).parent(canvasParentRef);
  };
  // additional code
}

@davepagurek
Copy link
Contributor

Does this still happen on the most recent version of p5? I suspect it may have been fixed by #5816. It looks like the version of react-p5 you linked is still using an old version of p5 (1.3.1; we're on 1.6.0 now): https://github.com/Gherciu/react-p5/blob/309723f4311a8cec5c7fe6d5b5da62b251efd26a/package.json#L59

If this no longer happens with vanilla p5, it could be worth making an issue in the react-p5 repo to ask them to update the p5 version.

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

Successfully merging a pull request may close this issue.

7 participants