balderdashy / sails

Realtime MVC Framework for Node.js
https://sailsjs.com
MIT License
22.84k stars 1.95k forks source link

Shell script not waiting for stream events #7200

Open ValentinSteiner opened 2 years ago

ValentinSteiner commented 2 years ago

Node version: v16.13.1 Sails version (sails): 1.4.2 ORM hook version (sails-hook-orm): sails-hook-orm@3.0.2 Sockets hook version (sails-hook-sockets): sails-hook-sockets@2.0.1 Organics hook version (sails-hook-organics): sails-hook-organics@2.2.0 Grunt hook version (sails-hook-grunt): sails-hook-grunt@4.0.1 Uploads hook version (sails-hook-uploads): n/a DB adapter & version (e.g. sails-mysql@5.55.5): n/a Skipper adapter & version (e.g. skipper-s3@5.55.5): n/a


Problem statement

I noticed that a shell script invoked through sails run myscript exits without waiting for a file stream to be read. I expected the node process to exit only after the file stream has been read entirely.

Steps to reproduce

module.exports = { friendlyName: 'myscript',

fn: function() {
    fs.createReadStream('/tmp/data.txt')
      .on('data', data => console.log(data.toString()))
      .on('end', () => console.log('ended'));
}

};


* Create a text file `/tmp/data.txt` with some text content.
* Run the command `sails run myscript`.

### Expected behavior
The script should print the contents of the file `/tmp/data.txt` to the console, followed by the string "ended".

### Observed behavior
The script exits without printing the file contents or "ended" to the console.

### Workaround
It's possible to wrap the reading of the file into a promise, await said promise and change the function to `async`:

const fs = require('fs');

module.exports = { friendlyName: 'myscript2',

fn: async function() {
    await new Promise((resolve, reject) => {
        fs.createReadStream('/tmp/data.txt')
          .on('data', data => console.log(data.toString()))
          .on('end', () => {
            console.log('ended');
            resolve();
        });
    });
}

};


### Remarks
Node normally waits for stream events, i.e. the following script `foo.js` does display the file contents before terminating (run via `node foo.js`):

const fs = require('fs');

fs.createReadStream('/tmp/data.txt') .on('data', data => console.log(data.toString())) .on('end', () => console.log('ended'));



It's unclear why the behavior is different when run as a Sails shell script.
sailsbot commented 2 years ago

@ValentinSteiner Thanks for posting! We'll take a look as soon as possible.

In the mean time, there are a few ways you can help speed things along:

Please remember: never post in a public forum if you believe you've found a genuine security vulnerability. Instead, disclose it responsibly.

For help with questions about Sails, click here.

eashaw commented 2 years ago

Hi @ValentinSteiner, The workaround you posted is how we recommend handling asynchronous scripts. You can look at the Parley readme to learn more about this.