termux-packages
termux-packages copied to clipboard
[Bug]: Nodejs uv_interface_addresses returned Unknown system error 13
Problem description
When I use the Termux app, install Node.js (latest and lts) and run Node.js - the call to os.networkInterfaces() works.
However when I build Node.js myself using the Termux Docker images (./build-package.sh openssl nodejs), each call to os.networkInterfaces() fails with A system error occurred: uv_interface_addresses returned Unknown system error 13 (Unknown system error 13) on my Android 11 system. (Permission denied).
it looks like this is because Android 11 forbids apps to query MAC addresses. Links:
- Analyse https://gitlab.com/staltz/manyverse/-/issues/1411
- a potential fix here https://github.com/JaneaSystems/nodejs-mobile/commit/73d5d375dbd672c3df8556a83ad122a078d21ed2
What steps will reproduce the bug?
start self compiled nodejs binary on your Android 11 phone, enter os.networkInterfaces()
in the repl.
Tested with the latest nodejs and nodejs-lts version
What is the expected behavior?
call does not fail
System information
termux-info:
Did you build in the docker image, or by git cloning termux-packages and running ./build-package.sh on device?
Building in the docker image should give an identical nodejs{-lts} package as the one in our repos, unless you've made changes to the build recipe?
I did git cloning termux-packages
and running ./build-package.sh - but not on the device but on my macbook.
And no changes to the nodejs packages - i basically followed https://github.com/termux/termux-packages/wiki/Build-environment and https://github.com/termux/termux-packages/wiki/Building-packages
more background information: I want to run a nodejs app on Android and use https://github.com/siepra/node-on-android-demo as starting point.
Note: I did NOT build the node package on my Android device, but on my Macbook in a Docker container. I the installed the node binary on my Android device. So I think the "on-device packaging" tag is wrong.
More info:
- the Android Termux App has targetSDK 28, that's why the os.networkInterfaces() call works
- if the Termux App targets SDK 30, the os.networkInterfaces() call will fail with the error described
@neophob Can you try building Node.js with the following additional patch:-
--- ./deps/uv/src/unix/linux-core.c.orig 2022-06-03 12:37:01.127102137 +0530
+++ ./deps/uv/src/unix/linux-core.c 2022-06-03 12:37:11.887102132 +0530
@@ -43,14 +43,6 @@
#include <fcntl.h>
#include <time.h>
-#define HAVE_IFADDRS_H 1
-
-#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
-# undef HAVE_IFADDRS_H
-# endif
-#endif
-
#ifdef HAVE_IFADDRS_H
# if defined(__ANDROID__)
# include "uv/android-ifaddrs.h"
This will make sure that uv_inteface_addresses()
will return UV_ENOSYS
which makes much more sense then failing as above.
Also would like to know what's your use case of os.networkInterfaces()
.
Thanks @thunder-coding ! I applied the patch building nodejs:
...
Applying patch: deps-uv-src-unix-core.c.patch
Applying patch: deps-uv-src-unix-net.c.patch << thats the patch above
Applying patch: deps-uv-src-unix-process.c.patch
Applying patch: deps-uv-uv.gyp.patch
Applying patch: deps-v8-src-flags-flag-definitions.h.patch
Applying patch: deps-v8-src-logging-log.cc.patch
Applying patch: deps-v8-src-trap-handler-trap-handler.h.patch
...
but then the build fails:
aarch64-linux-android-clang -o /home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/pthread-fixes.o ../deps/uv/src/unix/pthread-fixes.c '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-D__STDC_FORMAT_MACROS' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_GLIBCXX_USE_C99_MATH' -I../deps/uv/include -I../deps/uv/src -I/data/data/com.termux/files/usr/include -Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -g --std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wstrict-prototypes -fno-strict-aliasing -O3 -fno-omit-frame-pointer -fPIC -MMD -MF /home/builder/.termux-build/nodejs/src/out/Release/.deps//home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/pthread-fixes.o.d.raw -I/data/data/com.termux/files/usr/include -fstack-protector-strong -Oz -c
../deps/uv/src/unix/linux-core.c:636:38: warning: declaration of 'struct ifaddrs' will not be visible outside of this function [-Wvisibility]
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
^
../deps/uv/src/unix/linux-core.c:637:13: error: incomplete definition of type 'struct ifaddrs'
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
^
../deps/uv/src/unix/linux-core.c:637:42: error: incomplete definition of type 'struct ifaddrs'
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
^
../deps/uv/src/unix/linux-core.c:639:10: error: incomplete definition of type 'struct ifaddrs'
if (ent->ifa_addr == NULL)
~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
^
../deps/uv/src/unix/linux-core.c:645:10: error: incomplete definition of type 'struct ifaddrs'
if (ent->ifa_addr->sa_family == PF_PACKET)
~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
^
1 warning and 4 errors generated.
make[1]: *** [deps/uv/libuv.target.mk:141: /home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/linux-core.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:113: node] Error 2
Also would like to know what's your use case of os.networkInterfaces().
My use case is reuse a nodejs application in a mobile app. the os.networkInterfaces() call if not used directly - BUT there are some parts the use that code. the problem today is the error case which could lead to weird situations
@neophob The following updated patch should work:-
--- ./deps/uv/src/unix/linux-core.c.orig 2022-06-03 12:37:01.127102137 +0530
+++ ./deps/uv/src/unix/linux-core.c 2022-06-03 14:36:13.308341930 +0530
@@ -43,14 +43,6 @@
#include <fcntl.h>
#include <time.h>
-#define HAVE_IFADDRS_H 1
-
-#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
-# undef HAVE_IFADDRS_H
-# endif
-#endif
-
#ifdef HAVE_IFADDRS_H
# if defined(__ANDROID__)
# include "uv/android-ifaddrs.h"
@@ -640,7 +632,7 @@
return val;
}
-
+#ifdef HAVE_IFADDRS_H
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
@@ -654,6 +646,7 @@
return exclude_type;
return !exclude_type;
}
+#endif
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#ifndef HAVE_IFADDRS_H
And yeah, it's an upstream bug that uv__ifaddr_exclude
is compiled even when HAVE_IFADDRS_H
is not defined. The updated patch should fix it!
Also, the bug is fixed in libuv 1.44.1. Link to exact commit: https://github.com/libuv/libuv/commit/c40f8cb9f8ddf69d116952f8924a11ec0623b445. So no need to send it upstream, since they've already fixed it on their end :)
Nice, that patch worked.
Now i get a different error: A system error occurred: undefined returned undefined (undefined)
with stacktrace:
at Object.networkInterfaces (node:os:264:16)
at userspace js code where os.networkInterfaces() is used
Now i get a different error: A system error occurred: undefined returned undefined (undefined) with stacktrace:
Well that's because your code (or most probably one of your dependencies) hasn't been designed to work in situations where uv_network_interfaces
might not be implemented. Can you share the full stack trace, so that the culprit dependency (or your package) can be tracked
Well that's because your code (or most probably one of your dependencies) hasn't been designed to work in situations where uv_network_interfaces might not be implemented.
Not sure if I fully agree, as Nodejs docs say, that os.networkInterfaces()
returns an Object (which includes an empty object) - but a system error should not be thrown there.
Can you share the full stack trace, so that the culprit dependency (or your package) can be tracked
that IS the whole usable stacktrace of the code, my function call looks like return os.networkInterfaces();
, that's it. Here's the raw stacktrace:
"SystemError [ERR_SYSTEM_ERROR]: A system error occurred: undefined returned undefined (undefined)
at Object.networkInterfaces (node:os:264:16)
at E._getInterfaces (/data/data/app.fqdn/files/nodeapp/index.js:1:260599)
at E.getLanInterface (/data/data/app.fqdn/files/nodeapp/index.js:1:260702)
at E.getLanAddressIPv4 (/data/data/app.fqdn/files/nodeapp/index.js:1:260898)
at E.getLanAddress (/data/data/app.fqdn/files/nodeapp/index.js:1:261111)
at /data/data/app.fqdn/files/nodeapp/index.js:1:326359
at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/route.js:144:13)
at Route.dispatch (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/route.js:114:3)
at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
at /data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:284:15
at Function.process_params (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:346:12)
at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:280:10)
at Function.handle (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:175:3)
at router (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:47:12)
at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:328:13)
at /data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:286:9
at Function.process_params (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:346:12)
at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:280:10)
at Function.handle (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:175:3)
at router (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:47:12)"
is there anything I can do help diagnose this issue? I'm pretty clueless tbh at the moment, any hints are appreciated!
is there anything I can do help diagnose this issue? I'm pretty clueless tbh at the moment, any hints are appreciated!
It seems like you're using a bundler to bundle your application. If you can give me access to the source code of your app, I can certainly look into the place where os.networkInterfaces()
is called and whether there is a possible workaround for the same.
Best regards, Yaksh.
Yeah that is from the bundled version. Here's a copy of the code that crash
const os = require('os');
<snip>
SystemInfo.prototype._getInterfaces = function() {
return os.networkInterfaces(); << here the crash happens
};
SystemInfo.prototype.getLanInterface = function() {
const res = this._getInterfaces();
return res[this._ifaceNameLan];
};
as you can see, the code is pretty basic and it crashes when the os.networkInterfaces()
is used. The crash happens only if the Android targetSDK is set to 30+, it works when targetSDK is set to 28.
Thanks @thunder-coding for your feedback, is my example above enough or is there anything I can do to help you reproducing the problem?
Termux targets sdk level 28 for a reason, so I guess we won't be able to reproduce the issue in termux-app (and therefore @thunder-coding asked for access to the code of your app I guess).
IMHO this issue isn't really termux related. Maybe other nodejs developers can help if you open an issue in their repo
IMHO this issue isn't really termux related. Maybe other nodejs developers can help if you open an issue in their repo
Instead of opening the issue in the nodejs GitHub repo, it'll make more sense to open it in the package's repo which depends on os.networkInterfaces()
. Just grep through the node_modules/
directory to find out which package makes use of it.
Termux targets sdk level 28 https://github.com/termux/termux-app/issues/2155, so I guess we won't be able to reproduce the issue.
Yeah, I wanted to bring that issue up for the future (and my use case). Maybe it's my fault thinking that the termux packages support also post SDK 28 devices.
Instead of opening the issue in the nodejs GitHub repo, it'll make more sense to open it in the package's repo which depends on os.networkInterfaces().
This does not make sense as os.networkInterfaces()
is a NodeJS API call. There is no reason to use something else from a developers point of view.
This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I also meet the same problem, after some investigation, it was because the node had some problem, and I change a node for my pod then it solved, just share the info for others who may meet the same problem with me.
node:os:68
throw new ERR_SYSTEM_ERROR(ctx);
^
SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_interface_addresses returned Unknown system error 13 (Unknown system error 13) at Object.networkInterfaces (node:os:259:16)
at getAllIPAddresses (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/collector/facts.js:95:25)
at factMapCb (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/collector/facts.js:72:27)
at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:3681:19
at wrapper (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:271:20)
at iterateeCallback (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:427:28)
at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:327:20
at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:3679:17
at onRefreshFinish (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/environment.js:609:5)
code: 'ERR_SYSTEM_ERROR',
info: {
errno: 13,
code: 'Unknown system error 13',
message: 'Unknown system error 13',
syscall: 'uv_interface_addresses'
},
errno: [Getter/Setter],
syscall: [Getter/Setter]
}
Facing the same problem. Is there any workaround / temporary fix for this? uv_interface_addresses is pretty common node API. Almost any dev server relies on it.
@noonesimg The workaround is to use targets sdk level 28 - let me know if you found another solution
@neophob thanks! Can you specify plz, do I need to rebuild the whole termux-app with sdk level 28, or is there a way to just rebuild the nodejs package?
For those comming here after trying to use the C++ extension for code-server, I found a workaround:
- Format the file with the error with prettier
- npm i --global prettier
- prettier -w /data/data/com.termux/files/usr/lib/code-server/lib/vscode/out/vs/server/node/server.main.js
- Edit /data/data/com.termux/files/usr/lib/code-server/lib/vscode/out/vs/server/node/server.main.js and add befor line 16050 (the line with error, might be another line for you) to:
return '00:00:00:00:00:00';
So the whole function becomes:
function I() {
return '00:00:00:00:00:00';
const L = (0, os.networkInterfaces())();
for (const R in L) {
const b = L[R];
if (b) {
for (const { mac: d } of b) if (a(d)) return d;
}
}
throw new Error("Unable to retrieve mac address (unexpected format)");
}
I found this out after reading the documentation for os.networkInterfaces() and noticing that this function just returns the first mac address of the first interface in the system. Seems to work for me for now.