Closed neocturne closed 4 years ago
The patch looks okay to me. Maybe not great but it's not terrible either. We would have rejected it in the past due to our 'upstream first' policy but in the case of gyp that has been relaxed somewhat since upstream has largely abandoned it, effectively making us the maintainers.
You should file a pull request if you want to see the patch merged. I can't guarantee it actually gets merged but we will at least consider it, it won't be rejected outright.
I wonder though, what does ulimit -s
print on the system where you hit that issue? The size of the argument list is a function of the stack size. Increase the stack size enough and the problem should go away.
ulimit -s
is 8192 on my system, I don't think larger values are common. As it is execvp that fails, I think it rather hits ARG_MAX, which is 2MB on Linux and can't be changed.
Should I open a PR against the node repo, node-gyp, or both?
I think it rather hits ARG_MAX, which is 2MB on Linux and can't be changed.
That's only with really old kernels, though. On non-ancient kernels it's capped at 1/4th of the stack size.
$ ulimit -s
8192
$ strace -s10 -fe execve out/Release/node -e 'for (var a = [], i = 0; i < 16; ++i) a.push("x".repeat(0x1FFFF)); child_process.spawnSync("/bin/echo", a, {stdio:"ignore"})' 2>&1 | grep bin/echo
[pid 26094] execve("/bin/echo", ["/bin/echo", "xxxxxxxxxx"..., "xxxxxxxxxx"..., "xxxxxxxxxx"..., "xxxxxxxxxx"..., ...], [/* 35 vars */])
= -1 E2BIG (Argument list too long)
$ ulimit -s 32768
$ strace -s10 -fe execve out/Release/node -e 'for (var a = [], i = 0; i < 16; ++i) a.push("x".repeat(0x1FFFF)); child_process.spawnSync("/bin/echo", a, {stdio:"ignore"})' 2>&1 | grep bin/echo
[pid 26104] execve("/bin/echo", ["/bin/echo", "xxxxxxxxxx"..., "xxxxxxxxxx"..., "xxxxxxxxxx"..., "xxxxxxxxxx"..., ...], [/* 35 vars */])
= 0
The length of a single argument is restricted to 128 kB but that shouldn't be a problem because you're never going to have a path that long.
Should I open a PR against the node repo, node-gyp, or both?
node
Unfortunately, the patch I found doesn't work after all. I'll send PR as soon as I've found a working solution.
I've reworked the patch from OpenEmbedded for my own needs and it works fine with version 4.4.3. It is available here: https://github.com/riedonetworks/meta-nodejs/commits/dora/recipes/nodejs/files/0001-fix-execvp-printf-argument-list-too-long.patch
This issue has been inactive for sufficiently long that it seems like perhaps it should be closed. Feel free to re-open (or leave a comment requesting that it be re-opened) if you disagree. I'm just tidying up and not acting on a super-strong opinion or anything like that.
This issue has been inactive for sufficiently long that it seems like perhaps it should be closed.
But is it fixed? "inactive" could just mean that nobody with the ability to do anything about the issue is willing to do anything. That doesn't mean it's actually fixed though.
But is it fixed?
No, it is not fixed.
"inactive" could just mean that nobody with the ability to do anything about the issue is willing to do anything.
In this case, I think it means exactly that along with:
That doesn't mean it's actually fixed though.
That's correct. Believe me, if I could have closed this with "Fixed!" instead of "This issue has been inactive," I totally would have done that. I promise! 😆
Mostly what this needs is someone with the interest and the time to write a fix that will not be a maintenance burden or code smell. I suspect if you or anyone else were inclined to give it a try, we can find an experienced contributor on the project (perhaps @bnoordhuis?) who would be willing to answer questions that arise, review code after its written, and generally provide reasonable amounts of assistance.
Since obviously this is still causing problems for some small-but-very-real number of users, I'll re-open it and add a help wanted
label.
ulimit -s
to some high value is probably more palatable.That said, if you hit this issue while building node.js, you'll probably hit it sooner or later with another project too.
@bnoordhuis Perhaps we can consider this a documentation issue and add a note to a troubleshooting guide (or even right in BUILDING.md) explaining what to do when it arises?
Note that setting ulimit -s
had no effect on my system. The patch I provided in #9141 was the only way I could make it work.
Met the same problem today. Trying to build lede_17.01.4. Get the error:
make[4]: Entering directory '/data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/host/node-v4.4.5' make -C out BUILDTYPE=Release V=s make[5]: Entering directory '/data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/host/node-v4.4.5/out' make[5]: execvp: printf: Argument list too long deps/openssl/openssl.target.mk:862: recipe for target '/data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/host/node-v4.4.5/out/Release/obj.target/deps/openssl/libopenssl.a' failed make[5]: [/data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/host/node-v4.4.5/out/Release/obj.target/deps/openssl/libopenssl.a] Error 127 make[5]: Leaving directory '/data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/host/node-v4.4.5/out' Makefile:45: recipe for target 'node' failed make[4]: [node] Error 2
I dont need node-v4.4.5 package, but I dont know where to disable it. I unkecked all .js from menuconfig.
Changed root directory from: /data/openwrt_3/lede-sdk-17.01.4-brcm2708-bcm2709_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/ to /data/openwrt_3/lede/
And that solved my problem :)
Should this issue remain open? As pointed out, there's really not much we can do in Node.js for this
A pull request to https://github.com/nodejs/gyp-next is the way forward for anyone who wants to pick this up. I'll go ahead and close this out.
Hit this issue today and couldn't get one of the patch hunks to apply cleanly. After some formatting changes I got things going with node v14. Thought I'd share:
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py
index d163ae31..2ce1c301 100644
--- a/tools/gyp/pylib/gyp/generator/make.py
+++ b/tools/gyp/pylib/gyp/generator/make.py
@@ -155,6 +155,31 @@ cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
quiet_cmd_link = LINK($(TOOLSET)) $@
cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group
+# Note: this does not handle spaces in paths
+define xargs
+ $(1) $(word 1,$(2))
+$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2))))
+endef
+
+define write-to-file
+ @: >$(1)
+$(call xargs,@printf "%s\\n" >>$(1),$(2))
+endef
+
+OBJ_FILE_LIST := ar-file-list
+
+define create_archive
+ rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
+ $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
+ $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST)
+endef
+
+define create_thin_archive
+ rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
+ $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
+ $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST)
+endef
+
# We support two kinds of shared objects (.so):
# 1) shared_library, which is just bundling together many dependent libraries
# into a link line.
@@ -199,6 +224,31 @@ cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
quiet_cmd_alink_thin = AR($(TOOLSET)) $@
cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
+# Note: this does not handle spaces in paths
+define xargs
+ $(1) $(word 1,$(2))
+$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2))))
+endef
+
+define write-to-file
+ @: >$(1)
+$(call xargs,@printf "%s\\n" >>$(1),$(2))
+endef
+
+OBJ_FILE_LIST := ar-file-list
+
+define create_archive
+ rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
+ $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
+ $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST)
+endef
+
+define create_thin_archive
+ rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
+ $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
+ $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST)
+endef
+
# Due to circular dependencies between libraries :(, we wrap the
# special "figure out circular dependencies" flags around the entire
# input list during linking.
@@ -1766,14 +1816,28 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
self.flavor not in ("mac", "openbsd", "netbsd", "win")
and not self.is_standalone_static_library
):
- self.WriteDoCmd(
+ if self.flavor in ('linux', 'android'):
+ self.WriteMakeRule(
[self.output_binary],
link_deps,
- "alink_thin",
- part_of_all,
- postbuilds=postbuilds,
- )
+ actions = ['$(call create_thin_archive,$@,$^)']
+ )
+ else:
+ self.WriteDoCmd(
+ [self.output_binary],
+ link_deps,
+ "alink_thin",
+ part_of_all,
+ postbuilds=postbuilds,
+ )
else:
+ if self.flavor in ('linux', 'android'):
+ self.WriteMakeRule(
+ [self.output_binary],
+ link_deps,
+ actions = ['$(call create_archive,$@,$^)']
+ )
+ else:
self.WriteDoCmd(
[self.output_binary],
link_deps,
Hit this issue today and couldn't get one of the patch hunks to apply cleanly. After some formatting changes I got things going with node v14. Thought I'd share:
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index d163ae31..2ce1c301 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -155,6 +155,31 @@ cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) quiet_cmd_link = LINK($(TOOLSET)) $@ cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group +# Note: this does not handle spaces in paths +define xargs + $(1) $(word 1,$(2)) +$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2)))) +endef + +define write-to-file + @: >$(1) +$(call xargs,@printf "%s\\n" >>$(1),$(2)) +endef + +OBJ_FILE_LIST := ar-file-list + +define create_archive + rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST) +endef + +define create_thin_archive + rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST) +endef + # We support two kinds of shared objects (.so): # 1) shared_library, which is just bundling together many dependent libraries # into a link line. @@ -199,6 +224,31 @@ cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) quiet_cmd_alink_thin = AR($(TOOLSET)) $@ cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) +# Note: this does not handle spaces in paths +define xargs + $(1) $(word 1,$(2)) +$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2)))) +endef + +define write-to-file + @: >$(1) +$(call xargs,@printf "%s\\n" >>$(1),$(2)) +endef + +OBJ_FILE_LIST := ar-file-list + +define create_archive + rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST) +endef + +define create_thin_archive + rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST) +endef + # Due to circular dependencies between libraries :(, we wrap the # special "figure out circular dependencies" flags around the entire # input list during linking. @@ -1766,14 +1816,28 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD self.flavor not in ("mac", "openbsd", "netbsd", "win") and not self.is_standalone_static_library ): - self.WriteDoCmd( + if self.flavor in ('linux', 'android'): + self.WriteMakeRule( [self.output_binary], link_deps, - "alink_thin", - part_of_all, - postbuilds=postbuilds, - ) + actions = ['$(call create_thin_archive,$@,$^)'] + ) + else: + self.WriteDoCmd( + [self.output_binary], + link_deps, + "alink_thin", + part_of_all, + postbuilds=postbuilds, + ) else: + if self.flavor in ('linux', 'android'): + self.WriteMakeRule( + [self.output_binary], + link_deps, + actions = ['$(call create_archive,$@,$^)'] + ) + else: self.WriteDoCmd( [self.output_binary], link_deps,
this patch is awesome! the build works with 16 jobs. thanks!
with this patch, shortening build 1:30 hours to 10 minutes
@nxhack suggests, that i should instead of patching the build, just increase the ulimit -n 65535
build is runinng now. will let you if this modification is works.
@p3x-robot
@nxhack suggests, that i should instead of patching the build, just increase the
ulimit -n 65535
This is a different issue from what is being discussed in this thread.
why is it different?
@p3x-robot
As I pointed out elsewhere in my discussion with you, you need to separate the two events.
The need to increase file descriptors is only relevant for the latest binutils.
gotcha. there are 2 issues here, one is the node build and the binutils... ok clear.
my binutils are lower. so that is not the problem for me.
binutils-common/stable,now 2.35.2-2 amd64 [installed,automatic]
binutils-x86-64-linux-gnu/stable,now 2.35.2-2 amd64 [installed,automatic]
binutils/stable,now 2.35.2-2 amd64 [installed]
Hit this issue today and couldn't get one of the patch hunks to apply cleanly. After some formatting changes I got things going with node v14. Thought I'd share:
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index d163ae31..2ce1c301 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -155,6 +155,31 @@ cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) quiet_cmd_link = LINK($(TOOLSET)) $@ cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group +# Note: this does not handle spaces in paths +define xargs + $(1) $(word 1,$(2)) +$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2)))) +endef + +define write-to-file + @: >$(1) +$(call xargs,@printf "%s\\n" >>$(1),$(2)) +endef + +OBJ_FILE_LIST := ar-file-list + +define create_archive + rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST) +endef + +define create_thin_archive + rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST) +endef + # We support two kinds of shared objects (.so): # 1) shared_library, which is just bundling together many dependent libraries # into a link line. @@ -199,6 +224,31 @@ cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) quiet_cmd_alink_thin = AR($(TOOLSET)) $@ cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) +# Note: this does not handle spaces in paths +define xargs + $(1) $(word 1,$(2)) +$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2)))) +endef + +define write-to-file + @: >$(1) +$(call xargs,@printf "%s\\n" >>$(1),$(2)) +endef + +OBJ_FILE_LIST := ar-file-list + +define create_archive + rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST) +endef + +define create_thin_archive + rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)` + $(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2))) + $(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST) +endef + # Due to circular dependencies between libraries :(, we wrap the # special "figure out circular dependencies" flags around the entire # input list during linking. @@ -1766,14 +1816,28 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD self.flavor not in ("mac", "openbsd", "netbsd", "win") and not self.is_standalone_static_library ): - self.WriteDoCmd( + if self.flavor in ('linux', 'android'): + self.WriteMakeRule( [self.output_binary], link_deps, - "alink_thin", - part_of_all, - postbuilds=postbuilds, - ) + actions = ['$(call create_thin_archive,$@,$^)'] + ) + else: + self.WriteDoCmd( + [self.output_binary], + link_deps, + "alink_thin", + part_of_all, + postbuilds=postbuilds, + ) else: + if self.flavor in ('linux', 'android'): + self.WriteMakeRule( + [self.output_binary], + link_deps, + actions = ['$(call create_archive,$@,$^)'] + ) + else: self.WriteDoCmd( [self.output_binary], link_deps,
this patch is awesome! the build works with 16 jobs. thanks!
Thank you. This fixes the issue "printf: Argument list too long" we have at build time with nodejs 16.x!
Trying to build nodejs fails with the message
when the path to build directory is too long. We've hit this issue in OpenWrt/LEDE, but googling has turned up a lot of other people with the same issue.
I've found this patch to circumvent the issue in the OpenEmbedded patchwork: https://patchwork.openembedded.org/patch/72811/
Unfortunately, there is no further discussion and I have no idea why it is marked as superseded. I don't know the gyp code at all, so I can't tell if the patch is okay like this, but unconditionally using the filename
ar-file-list
seems a bit weird to me...