Currently, I'm running a node js program with the debugger.
the program uses a lot of promises and using a library called p-limit
and I put the debugging config to skip node internal and node modules.
"skipFiles": [
"<node_internals>/**/*.js",
"${workspaceFolder}/node_modules/**/*.js",
]
It's a long running program, it eats cpu and network a lot.
Then I notice the program doesn't eat CPU and network anymore.
So I assume it's stuck and hit the pause button
Somehow the program went stuck at the file called stuctured-stack
(function() {
Error.prepareStackTrace = function(err, trace) {
err.stack = trace;
};
Error.stackTraceLimit = Infinity;
return function structuredStack() {
return new Error().stack;
};
})()
there's no error thrown and it seems not doing anything
What does this mean?
Edit
Added a screenshot:
Related
I'm trying to get a list of currently connected wifi SSID's, for which I use the node-wifi library, I tried with a very basic block of code, which is working in regular node. However even after doing a rebuild of the dependencies with qode I don't get it to work in nodegui, I started from the react-node-gui starter and added a button which calls this code:
import wifi from "node-wifi"
export const getCurrentWifiConnection = async () => {
wifi.init({iface: null})
console.log("lets get the networks...")
let currentConnections
try{
currentConnections = await wifi.getCurrentConnections()
console.log(currentConnections)
} catch(e) {
console.log(e)
}
return currentConnections
}
anyone who has an idea of what's going on?
I don't see anything from my console.log with the current-connections or from the error (doesn't matter if I use console.log or console.error) the "let's get the networks" log message gets printed though, so the function is getting called.
I've tested this code on node-16 and it's running perfectly if nodegui isn't wrapped around it, I know nodegui is using it's own customized node runtime with extra bindings for QT events, so I believe this has something to do with the qode.
Is possible to restart automatically a node cli script when it's finished to execute the code?
I have this cli script that will run until a variable reach a limit
const maxExecution = 200;
let i = 0;
let task = setInterval( () => {
i++;
if( i >= maxExecution ){
clearInterval(task);
}
// code here...
},5000);
This code will work fine and will stop the tasks when the i variable reach the set limit. I'm reading this question about how to manage process.exit. Is there any event I can listen to understand if the script execution have reached the end?
I had this code (typescript, not vanilla nodejs) when I was working with node<=10 (possibly between 6 ~ 10, not quite sure), it can restart itself on-demand:
import { spawn } from "child_process";
let need_restart:boolean=false;
process.on("exit",function(){
if(need_restart){
spawn(process.argv.shift(),process.argv,{
"cwd":process.cwd(),
"detached":true,
"stdio":"inherit"
});
}
});
It's part of a http/ws server, when all server closed (no more event), the process automatically exit. By setting the need_restart to true, it will restart itself when this happen.
I haven't used node for quite some time, so I'm not sure if this still work on later version, but I think it's worth mentioning it here.
I have made a Node.js script which checks for new entries in a MySQL database and uses socket.io to send data to the client's web browser. The script is meant to check for new entries approximately every 2 seconds. I am using Forever to keep the script running as this is hosted on a VPS.
I believe what's happening is that the for loop is looping infinitely (more on why I think that's the issue below). There are no error messages in the Forever generated log file and the script is "running" even when it's started to hang up. Specifically, the part of the script that hangs up is the script stops accepting browser requests at port 8888 and doesn't serve the client-side socket.io js files. I've done some troubleshooting and identified a few key components that may be causing this issue, but at the end of the day, I'm not sure why it's happening and can't seem to find a work around.
Here is the relevant part of the code:
http.listen(8888,function(){
console.log("Listening on 8888");
});
function checkEntry() {
pool.getConnection(function(err,connection) {
connection.query("SELECT * FROM `data_alert` WHERE processtime > " + (Math.floor(new Date() / 1000) - 172800) + " AND pushed IS NULL", function (err, rows) {
connection.release();
if (!err) {
if(Object.keys(rows).length > 0) {
var x;
for(x = 0; x < Object.keys(rows).length; x++) {
connection.query("UPDATE `data_alert` SET pushed = 1 WHERE id = " + rows[x]['id'],function() {
connection.release();
io.emit('refresh feed', 'refresh');
});
}
}
}
});
});
setTimeout(function() { checkEntry();var d = new Date();console.log(d.getTime()); },1000);
}
checkEntry();
Just a few interesting things I've discovered while trouble shooting...
This only happens when I run the script on Forever. Work's completely fine if I use shell and just leave my terminal open.
It starts to happen after 5-30 minutes of running the script, it does not immediately hang up on the first execution of the checkEntry function.
I originally tried this with setInterval instead of setTimeout, the issue has remained exactly the same.
If I remove the setInterval/setTimeout function and run the checkEntry function only once, it does not hang up.
If I take out the javascript for loop in the checkEntry function, the hang ups stop (but obviously, that for loop controls necessary functionality so I have to at least find another way of using it).
I've also tried using a for-in loop for the rows object and the performance is exactly the same.
Any ideas would be immensely helpful at this point. I started working with Node.js just recently so there may be a glaringly obvious reason that I'm missing here.
Thank you.
So I just wanted to come back to this and address what the issue was. It took me quite some time to figure out and it can only be explained by my own inexperience. There is a section to my script where my code contained the following:
app.get("/", (request, response) => {
// Some code to log things to the console here.
});
The issue was that I was not sending a response. The new code looks as follows and has resolved my hang up issues:
app.get("/", (request, response) => {
// Some code to log things to the console here.
response.send("OK");
});
The issue had nothing to do with the part of the code I presented in the initial question.
I've created an app using Electron, and bundled it in an .exe file with electron-builder.
When I run the generated executable, the application starts with the default installation GIF used by electron-builder, as expected.
After the GIF finishes, the app restarts and works properly. It even appears in control panel's programs list.
However, if I look for it in the start menu applications, it isn't there (and searching it by its name only returns the aforementioned .exe installer).
Because of this, once the app is closed, the only way to open it back is running again the installer.
Why does this happen? Is there any way to make it appear with the other programs?
The electron-builder installer (and electron-windows-installer) use Squirrel for handling the installation. Squirrel launches your application on install with arguments that you need to handle. An example can be found on the windows installer github docs
Handling Squirrel Events
Squirrel will spawn your app with command line flags on first run, updates, and uninstalls. it is very important that your app handle these events as early as possible, and quit immediately after handling them. Squirrel will give your app a short amount of time (~15sec) to apply these operations and quit.
The electron-squirrel-startup module will handle the most common events for you, such as managing desktop shortcuts. Just add the following to the top of your main.js and you're good to go:
if (require('electron-squirrel-startup')) return;
You should handle these events in your app's main entry point with something such as:
const app = require('app');
// this should be placed at top of main.js to handle setup events quickly
if (handleSquirrelEvent()) {
// squirrel event handled and app will exit in 1000ms, so don't do anything else
return;
}
function handleSquirrelEvent() {
if (process.argv.length === 1) {
return false;
}
const ChildProcess = require('child_process');
const path = require('path');
const appFolder = path.resolve(process.execPath, '..');
const rootAtomFolder = path.resolve(appFolder, '..');
const updateDotExe = path.resolve(path.join(rootAtomFolder, 'Update.exe'));
const exeName = path.basename(process.execPath);
const spawn = function(command, args) {
let spawnedProcess, error;
try {
spawnedProcess = ChildProcess.spawn(command, args, {detached: true});
} catch (error) {}
return spawnedProcess;
};
const spawnUpdate = function(args) {
return spawn(updateDotExe, args);
};
const squirrelEvent = process.argv[1];
switch (squirrelEvent) {
case '--squirrel-install':
case '--squirrel-updated':
// Optionally do things such as:
// - Add your .exe to the PATH
// - Write to the registry for things like file associations and
// explorer context menus
// Install desktop and start menu shortcuts
spawnUpdate(['--createShortcut', exeName]);
setTimeout(app.quit, 1000);
return true;
case '--squirrel-uninstall':
// Undo anything you did in the --squirrel-install and
// --squirrel-updated handlers
// Remove desktop and start menu shortcuts
spawnUpdate(['--removeShortcut', exeName]);
setTimeout(app.quit, 1000);
return true;
case '--squirrel-obsolete':
// This is called on the outgoing version of your app before
// we update to the new version - it's the opposite of
// --squirrel-updated
app.quit();
return true;
}
};
Notice that the first time the installer launches your app, your app will see a --squirrel-firstrun flag. This allows you to do things like showing up a splash screen or presenting a settings UI. Another thing to be aware of is that, since the app is spawned by squirrel and squirrel acquires a file lock during installation, you won't be able to successfully check for app updates till a few seconds later when squirrel releases the lock.
In this example you can see it run Update.exe (a squirrel executable) with the argument --create-shortcut that adds start menu and desktop shortcuts.
It's 2021 and I am still having a very similar problem.
My app installs correctly and with the script above it also successfully adds a Desktop link to my app. BUT: There is no Shortcut being added to the Windows Start Menu.
With the script above this should also be added to the Start Menu, right?
One comment above says:
// Install desktop and start menu shortcuts
spawnUpdate(['--createShortcut', exeName]);
What am I missing? Any hint highly appreciated...
For me it helped to add icon and setupIcon to the package.json file, where the makers, are configured. Before my app didnt show up in the Start menu, and with the maker config as below, it does. I am not sure why though.
"makers": [
{
"name": "#electron-forge/maker-squirrel",
"config": {
"name": "cellmonitor",
"icon": "favicon.ico",
"setupIcon": "favicon.ico"
}
}
]
I am having troubles with getting child_process working with Atom Electron. First of all, I am using the pre-compiled binary app that you can download from Electron's website:
I am using the usual pre-compiled binary on Mac OS X.
In myapp.app/Contents/Resources I made a folder app as described.
I added a brief package.json inside it, setting index.js as main script.
Now, if I add to index.js the following snippet:
'use strict';
var electron = require('electron');
var app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var mainWindow;
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600});
mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.webContents.openDevTools();
mainWindow.on('closed', function()
{
mainWindow = null;
});
}
app.on('ready', createWindow);
app.on('window-all-closed', function () {
if (process.platform !== 'darwin')
{
app.quit();
}
});
app.on('activate', function () {
if (mainWindow === null)
{
createWindow();
}
});
(that is basically the example code to get things working) everything works fine. I get the window and I can get it to do basically anything.
Now, for reasons related to updates, I am in need to slightly change this paradigm. What I would need is to be able to perform several tasks from index.js without any need to do any gui operation (it should be some sort of daemon) and then to start some child.js script as a child_process from index.js. child.js should be able to open windows and all the rest.
So here was my naive try. I just cut and pasted the example snippet above in child.js, then edited index.js into the following:
var child_process = require('child_process');
var my_child = child_process.fork(__dirname + '/child.js');
Quite minimal, right? Hoped it would work, but it didn't. When I double click on my pretty app, nothing happens. I bet I am doing something wrong in a trivial way, but I wouldn't be able to tell what.
Update 1 I moved this out of my package so that I could get console.logs. child.js dies with an error at require('electron'): it doesn't seem to be able to find it.
Update 2: I listed the environment variables in child.js and noticed a ATOM_SHELL_INTERNAL_RUN_AS_NODE = 1. I thought I should turn that to 0, but nothing changed.
In Electron child_process.fork() will spawn the child with the ATOM_SHELL_INTERNAL_RUN_AS_NODE environment variable set, which means that no Chromium features will be available in the child process (so no Electron built-in modules), all you'll get is the vanilla Node runtime plus a patched fs that can read inside ASAR files. If you look at the code for child_process.fork() you'll see there's no way to override the value of ATOM_SHELL_INTERNAL_RUN_AS_NODE. If you can, use child_process.spawn() instead, failing that I guess you could try opening an issue and asking if the Electron team will be open to modifying the current behavior.