crucialfelix/supercolliderjs

sclang timeout on electron build

fibonacid opened this issue ยท 19 comments

Sclang booting reaches timeout on electron but only on the production build.

This is the log:

Loading config: /Users/lorenzo/Developer/Node/superorch/.supercollider.yaml
debug  : {
          "debug": true,
          "echo": true,
          "sclang": "/Applications/SuperCollider/SuperCollider.app/Contents/MacOS/sclang",
          "scsynth": "/Applications/SuperCollider/SuperCollider.app/Contents/Resources/scsynth",
          "stdin": false,
          "failIfSclangConfIsMissing": false,
          "conf": {
            "includePaths": [],
            "excludePaths": [],
            "postInlineWarnings": false
          },
          "sclang_conf": "/Users/lorenzo/Library/Application Support/SuperCollider/sclang_conf.yaml"
        }
debug  : {
          "errno": -2,
          "syscall": "open",
          "code": "ENOENT",
          "path": "/Users/lorenzo/Library/Application Support/SuperCollider/sclang_conf.yaml"
        }
[ 101, 'connection open' ]
debug  : compiling class library...
[Error: net::ERR_HTTP_RESPONSE_CODE_FAILURE]
error  : Timeout waiting for sclang to boot pid:28774
SCError {
  data: SclangCompileResult {
    version: '',
    stdout: '',
    errors: [],
    extensionErrors: [],
    duplicateClasses: [],
    dirs: []
  }
}

How to reproduce this issue:

  • Create React App + Electron setup
  • On App.js use an electron channel to boot sclang

Environment

  • MacOS: 10.15
  • electron: 7.1.2
  • electron-builder: 21.1.1
  • SuperColliderjs 1.0.0-beta.1

Sorry, it's been the craziest week of the year. I'll have a chance to peek at that over the holidays. Thanks!

Less crazy, but still crazy. Sorry that I haven't had the time to look into this yet.

I rebuilt the project from scratch with a new electron configuration and the problem doesn't persist.

The compilation of the class library fails because sclang_config.yml is not defined.
I solved this problem by manually creating the file with default parameters.

nano  ~/Library/Application\ Support/SuperCollider/sclang_conf.yaml
includePaths: []
excludePaths: []
postInlineWarnings: false

Then the error from before disappear, but the compilation fails again.

# launch the app from terminal to see the error message
myapp/dist/mac/myapp.app/Contents/MacOS/myapp
SCError {
  data: SclangCompileResult {
    version: '',
    stdout: '',
    errors: [],
    extensionErrors: [],
    duplicateClasses: [],
    dirs: []
  }
}

here is a repo to test the problem
https://github.com/lorenzorivosecchi/superorch-client

That's surprising. I was pretty sure it wasn't needed.

This is happening only on the built version of the app via electron builder.
Could there be some dependency of supercolliderjs that is missing from the asar archive ?

What could I do to have more detailed log of the error ?
(When I launch sclang from the terminal everything works fine)

Ah, you need to have a portable copy inside your electron bundle!

You can't use your /Application one. Electron cannot access anything outside of it's package.

This project is 3 years old but might give you some help:
https://github.com/experimentalDataAesthetics/play-splom/blob/master/README.md#play-splom

I manually copied scsynth etc. into app/vendor. There is a script shown there for launching scsynth.

You could do the same for sclang.

Look at the SoundApp that starts it up:
https://github.com/experimentalDataAesthetics/play-splom/blob/master/app/sound/SoundApp.js

This is all very fragile. I always wanted to get an npm package that includes a portable scsynth and sclang. That would be ideal.

sclang can be a problem to make it portable. The way it's built it depends on having the Qt packages in the exact same relative paths. I had problems trying to fix all the linking.

This was the project I did: https://medium.com/@crucialfelix/experimental-data-aesthetics-4563d01a5ebb

I had hoped that Electron would be easier to work with.

Hi @crucialfelix, i have managed to get sclang to work from the terminal.
Here is an explanation of what I did.

Here is the file structure I ended up with.

public
โ”œโ”€โ”€ assets
โ”œโ”€โ”€ electron.js
โ”œโ”€โ”€ index.html
โ””โ”€โ”€ vendor
    โ””โ”€โ”€ supercollider
        โ””โ”€โ”€ osx
            โ”œโ”€โ”€ README.md
            โ”œโ”€โ”€ bundle
            โ””โ”€โ”€ sclang.sh

Now I am having a little bit of trouble understanding how to link supercolliderjs.lang and my sclang.sh script. Can you give me a hint ?

Thank you very much btw

Almost solved:

I'm passing the correct sclang path to supercolliderjs via options.
The problem now is that function _spawnProcess raises an error.

{ 
  errno: 'ENOTDIR',
  code: 'ENOTDIR',
  syscall: 'spawn'
}

I've put a console log inside the function to see what's wrong.

console.log(execPath, commandLineOptions);

This is the result:

[%APP_PATH%]/Contents/Resources/app.asar/vendor/supercollider/osx/MacOS/sclang 
[
  '-i',
  'supercolliderjs',
  '-l',
  '/var/folders/vr/jrjfpdnj4wq5pwl65rnb9hy40000gn/T/sclang-conf2020118-33936-7lduqq.r96df'
]

@crucialfelix seems like path.dirname is not working as expected, could this be related to compatibility issues with the asar format ?

I seem to remember that asar is an isolated filesystem. The path as seen by the node process running in electron is not the full host path. Can you look again at the example app from 2017? Things may have changed since then. Not sure

Yes, the official guidelines say that using cwd on child_process.spawn is not permitted.

Though asar archives are treated as directories, there are no actual directories in the filesystem, so you can never set the working directory to directories in asar archives. Passing them as the cwd option of some APIs will also cause errors.

Update:

I got around the problem by keeping every supercollider resource, including supercolliderjs, in a unpackaged directory called app.asar.unpackaged.

Now when I call sclang through a shell script, like in play-splom, the class libraries get compiled, but no connection between node and the process is created.
If instead I call the sclang binary directly, all works great in development but fails on production.

What is the difference between passing a script to options.sclang rather then the actual binary ?

The script is to change your CWD. The way that sclang is linked and compiled, it assumes that you are calling the binary from that directory. The links to the other binary objects are relative to CWD (current working directory).

So as long as the process sets the cwd correctly, you can get away with not using the script.

When you are done I will put together a document of all you've discovered. I'll add it to the docs as a markdown.

Ok, I've found a solution.

Basically every module required by supercolliderjs must be unpacked, therefore being located inside MyApp/Contents/Resources/app.asar.unpacked.

Also all path statements that involve unpacked modules should be modified to point to app.asar.unpacked rather then app.asar.
To do this I have found this library called hazardous that does that for you.

@crucialfelix I've created an example repo that you can use as a reference.
https://github.com/lorenzorivosecchi/electron-with-supercollider-example