Node C++ extension loading in docker only Segfault on Google Compute Engine - javascript

I am experiencing an extremely weird behavior with docker containers + node on Google Compute Engine.
The setup is the following:
I have a docker image pushed to a private docker registry
This image is created on top of ubuntu 12.04 (FROM ubuntu:12.04)
The code i am running is javascript Node code with a C++ extension.
The C++ extension contains custom C++ code as well as dynamically linked libraries (boost, blas, armadillo, etc...)
I tried running the docker container with the node code + extension on many different machines (local, and different instance sizes on AWS).
It segfaults when i launch the exact same container on GCE. It crashes on different machines and different OSs.
This is the output i get when using this tool (I run the command from inside the container):
/opt/th/api# node start.js
PID 118 received SIGSEGV for address: 0x7f1c7faab000
/opt/th/api/node-segfault-handler/build/Release/segfault_handler.node(+0x100d) [0x7f1c8b2fa00d]
/lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0)[0x7f1c8b8cbcb0]
/usr/lib/libblas.so(+0x3d6fd8)[0x7f1c89229fd8]
/usr/lib/libblas.so(blas_memory_alloc+0x34d)[0x7f1c8922a70d]
/usr/lib/libblas.so(gotoblas_init+0x30)[0x7f1c88efb120]
/lib64/ld-linux-x86-64.so.2(+0xf306)[0x7f1c8c70a306]
/lib64/ld-linux-x86-64.so.2(+0xf3df)[0x7f1c8c70a3df]
/lib64/ld-linux-x86-64.so.2(+0x13ada)[0x7f1c8c70eada]
/lib64/ld-linux-x86-64.so.2(+0xf176)[0x7f1c8c70a176]
/lib64/ld-linux-x86-64.so.2(+0x1331a)[0x7f1c8c70e31a]
/lib/x86_64-linux-gnu/libdl.so.2(+0xf26)[0x7f1c8c4f7f26]
/lib64/ld-linux-x86-64.so.2(+0xf176)[0x7f1c8c70a176]
/lib/x86_64-linux-gnu/libdl.so.2(+0x152f)[0x7f1c8c4f852f]
/lib/x86_64-linux-gnu/libdl.so.2(dlopen+0x31)[0x7f1c8c4f7fc1]
node(uv_dlopen+0x30)[0x966000]
node(_ZN4node6DLOpenERKN2v89ArgumentsE+0xee)[0x818bfe]
node[0x5c7c0b]
[0xf956706362]
Has anyone seen anything like this?
It looks like a dynamic linking problem. But why would I only see this on GCE and nowhere else?

Update
After long hours of fighting with this problem, I found a solution by rebuilding the container with a different version of blas. I installed the atlas package (libatlas-dev libatlas-base-dev), recompiled with it, rebuilt the container, and didn't have the segfault anymore.
Still: no idea why the previous container didn't work on GCE (whereas it worked perfectly on AWS)...

Related

Running tensorflow from another code base

I'm hoping someone can help me out here as I feel like I've literally tried everything.
I've followed the tensorflow for poets tutorial for image classification and it works great. I've now built a node application and I'm using a package called python-shell which lets you run python scripts, which also works (I am aware of tensorflow js but I need the performance of py). I've plugged it up so that it can run my tensorflow image classifier and it seems to work...ish. The scripts are definitely executing but when it comes to reading retrained_labels.txt this is where it fails.
The error I get back is:
tensorflow.python.framework.errors_impl.NotFoundError: NewRandomAccessFile failed to Create/Open: tf_files/retrained_labels.txt : The system cannot find the path specified.
From what I've read this is a paths issue and I've already tried to specify absolute paths in my retrain script, but it doesn't solve the issue. However the issue isn't really with tensorflow as that works perfectly as a stand alone script.
I'm at a complete loss so any suggestion is much appreciated.
For some more context the code I need to run is:
py -m scripts.label_image --graph="tf_files/retrained_graph.pb --image=tf_files/dogs/test.jpg
In my node app I'm running this (and I've also played with different script paths, absolute paths, relative paths and every combination I can think of for the last 6 hours)
let options = {
scriptPath: './playground/',
args: ['--graph', './playground/tf_files/retrained_graph.pb', '--image', './playground/tf_files/dogs/test.jpg']
};
PythonShell.run('scripts/label_image.py', options, function (err, pyRes) {
if (err) throw err;
res.send({ result: pyRes });
});
Is there a way I can maybe run a python script which then goes and runs this?
py -m scripts.label_image --graph="tf_files/retrained_graph.pb --image=tf_files/dogs/test.jpg
Finally fixed by hard coding absolute path in image_label.py

NodeJS Javascript piece code running on Windows but not on Linux

I am particularly new to NodeJS and Javascript and have created a small web Application. I have my code running on Windows machine seamlessly. However, When I tried running it on a Linux VM it blocked at a point with no error or Exceptions thrown.
I discovered there was a line which actually caused a blockage in Linux, commented it out and the code continued from there on limiting the Application's functionality which greatly depends on that line with the other independent parts being functional.
....
var localEntry = entry.split('\\')
if(!localEntry)
localEntry = entry.split('/')
localEntry = localEntry[localEntry.length -1]
this.scripts[extn][localEntry].day1Vars = searchedVars[entry].day1Vars
}
I was extremely puzzled to find the exact same code running seamlessly on a Windows machine and blocking on a Linux vm due to a single line of code and am wondering how that could be ? The line which is responsible for such behavior is :
this.scripts[extn][localEntry].day1Vars = searchedVars[entry].day1Vars
My expectation is code on Node.js is platform independent and the thought of a line of code causing such difference is revolting.
I am using Windows 10 and RHEL 6.9 with 8GB of ram in both.
Could someone guide me if I am missing something or what has gone wrong?
Any help is greatly appreciated.
As requested by folks here, Sample values(on Windows) :
entry : "d:\NodeProjects\BApp\uploads\bp\bp\scripts\nodejs\set-nodejs-root.sh"
localEntry : "set-nodejs-root.sh"
Its better to check what is the environment.
For example you should split in:
ubuntu .split("/")
windows .split("\\")
Looks like you are working with paths, the best recommendation here is to use the path module to handle those routes for you:
https://nodejs.org/api/path.html
Here is a good explanation on how to handle routes for both systems:
https://nodejs.org/api/path.html#path_windows_vs_posix
I would use something like
https://nodejs.org/api/path.html#path_path_parse_path
To parse the paths correctly or if you need to construct paths you can use:
https://nodejs.org/api/path.html#path_path_join_paths
Check all different options there, I am 99% sure that you will find the proper method for your use case
When you specify a path under windows you have to use "\"
Linux uses "/" for path

Why don't web workers work?

So, I'm trying to use a web worker in my project to run a long-running process that is currently tying up the UI. I've been to I don't know how many sites trying to get a worker to work, but to no avail.
All of my javascript is kept in separate files and referenced in the HTML file. As a test to get my feet wet, I created a test.js file and put the following code in it:
self.addEventListener('message', function(e) {
self.postMessage('return');},false);
Then, in the UI page's javascript file I placed this code in a function triggered by a button click event:
var w = new Worker('test.js');
w.addEventListener('message',function(e){
alert(e.data);},false);
w.postMessage('hi');
The code is derived from:
html5rocks.com/en/tutorials/workers/basics
Other websites I visited provided similar instructions on how to set up a worker.
For the life of me, I cannot get this to work. When I execute it does absolutely nothing and I seemingly get no errors. Stepping through the code, it appears to create the worker, but I don't see any evidence of the event listener being created and the 'postMessage' event doesn't do anything. I've tried IE11 and Chrome with the same results.
In my research, I came across a part of Chrome's developer tools that revealed the test.js file couldn't be found. Yet, the file is in the same folder as the page's js file. So, I tried adding in the relative directory information as I do in the page's HTML section. That didn't work either.
I then found claims that for security reasons you couldn't have one js file reference another js in the code. It's unclear whether this is a Chrome-only feature or part of some spec.
So, now I'm in a quandary. The worker requires a reference to a separate js file for the code to be executed, yet, the browser isn't allowed to reference another file? How is the worker supposed to work if you aren't allowed to do what it requires to work?
To now, I've successfully pissed away two days trying to get this one seemingly simple function to work. To say I'm mildly frustrated would be an understatement. Being a fairly novice programmer and not understanding every last little nuance about web programming I'm clearly missing a key part of this whole thing.
How the heck is one supposed to make web workers work?
Turns out browsers won't allow local files to be fetched via javascript. Because that means a website can read your personal files! So you need to develop and test your project using a web server. The easiest way to do this for me was to install:
docker-compose
and make sure it works. Then create a file named:
docker-compose.yml
inside root folder of my project with index.html file. Then put this inside the docker-compose.yml file:
version: '3'
services:
nginx:
image: nginx:alpine
volumes:
- .:/usr/share/nginx/html
ports:
- "80:80"
Then inside the root folder of my project run:
docker-compose up
And then in the browser go to:
http://localhost/
And it worked!
I appear to have found a solution, though it escapes me why.
If I use:
var w = new Worker('js\test.js');
the worker doesn't work.
But, if I use:
var w = new Worker('js/test.js');
the worker does work.
I characteristically use the back slash throughout the project to delineate paths without issue. Why the forward slash must be used to set the worker's file location is a mystery. I have seen nothing in any documentation that even remotely addresses that tiny, yet seemingly critical detail.
Thank you, Mr. Starke, for your help!

How do I change the underlying Phantomjs object settings using Chutzpah?

We have some QUnit javascript tests running in Visual Studio using the Chutzpah test adapter. Everything was working fine until we changed our api (the one being tested by the js files) recently, and added some validations over the UserAgent http header. When I tried to update the tests to change/mock the user agent I realized it was not directly possible even by overriding the default browser property.
After a few days of scavenging, I finally found what exactly is happening. Chutzpah is creating a phantomjs page object for the test files to run on. This is being done on a base javascript file (chutzpahRunner.js) located at the Chutzpah adapter installation path. These are the last lines on the file, that effectively start the tests:
...
// Allows local files to make ajax calls to remote urls
page.settings.localToRemoteUrlAccessEnabled = true; //(default false)
// Stops all security (for example you can access content in other domain IFrames)
page.settings.webSecurityEnabled = false; //(default true)
page.open(testFile, pageOpenHandler);
...
Phatomjs supports changing the user agent header by specifying it in the page settings object. If I edit this chutzpahRunner.js file in my machine, and manually set the user agent there, like this:
page.settings.userAgent = "MyCustomUserAgent";
My tests start to work again. The problem is that this is not in the project itself, and thus cannot be shared with the rest of the team.
Is it possible to change the properties of the phantomjs objects created by Chutzpah to run the tests? I'd like to either change them from inside my own tests, or from another script file I could embed on the pipeline.
Without a code change in Chutzpah it is not possible to set those properties on the PhantomJS object. Please file an issue at https://github.com/mmanela/chutzpah asking for this functionality and then fork/patch Chutzpah to add it (or wait for a developer on the project to hopefully get to this).
Update:
I pushed a fix for this issue. Once this is released you can use the following in a Chutzpah.json file:
{
"userAgent": "myUserAgent"
}

path- and other problems using node.JS and Socket.IO

I'm using node.JS in VirtualBox on a TurnkeyLinux hosted by Windows. I was following the instructions here. node.JS is living in /root/node. Although I can run simple examples successfully I'm having a hard time figuring out certain things, cause I'm not a Linux-guy normally. I wanted to use socket.io.
I managed installing node.JS itself using git and tried that with Express and Socket.IO too. (e.g. git clone git://github.com/LearnBoost/Socket.IO.git). It seems to work, but I can't find that stuff anywhere! Was in /root/node when calling git, expecting changes in the lib-folder...
node.JS is using the CommonJS module system. In the Socket.IO example io = require('../') is used to import Socket.IO which looks pretty strange to me. Other expamples on the web are referring to './Socket.IO-node'. As a module is just a JS-file following certain rules I would expect sth like a path to such a file, as I found http.js in /root/node/lib.
By the way, looking at the server.js example: Is there a certain reason using var for http, but not for the rest of the variables (url, fs, io, sys)?
On clientside the first line on "How to use" Socket.IO is: io.setPath(...). setPath is not mentioned anywhere else on the page. Where should it point to, relative to what?
I've found no information about stoping/restarting node using the shell. Probably it's so obvious, that it's never mentioned anywhere ;)
Thanks for helping out.
The git-version that comes with the Turnkey-Core these days is quite outdated. Maybe this is causing problems. I worked around using my git on windows and WinSCP ;)
There is an inbuild automatism that index.js is used by default like index.html is used by default on webservers. So '../' is pointing to index.js in the parent folder, which then exports the listener of socket.io. Guillermo Rauch has put an index.js in the socket.io-folder now, so sth like './lib/socket.io/' is working. Note that there are examples out there with sth like './socket.io/socket.io.js', but socket.io.js doesn't exist anymore for some good reasons.
Of course the var is used for all variables. I've seen the commas as semicolons. Maybe I should change my screen-resolution ;)
It comes clear when looking at the example. setPath points to the folder where socket.io.js and it's lib-directory lives, relative to the html-file that uses it. This is needed for the flash-sockets to work.
Well, it's not that simple. You may look up the PID usind 'ps ux' and then 'kill' the process using the PID. A better way is using upstart. Or you do it by code using autorestart.

Categories