rmyorston / busybox-w32

WIN32 native port of BusyBox.
https://frippery.org/busybox
Other
670 stars 124 forks source link

Can't use ulimit in Makefile when using busybox-w32 make #408

Closed smalltalkman closed 4 months ago

smalltalkman commented 4 months ago

When using ulimit in Makefile:

check-regression: tests/config-flags.pm
@rm -f $(testfiles)
if test -f '$(top_srcdir)/tests/run_make_tests'; then \
echo "======|===$$(which echo)"; \
echo "======|===$$(which tar)"; \
echo "======|===$$(which ulimit)"; \
ulimit -n 128; \
echo "======|===running ...."; \
else \
echo "Can't find the $(PACKAGE_NAME) test suite ($(top_srcdir)/tests)."; \
fi

Report an error directly:

make check-local
if test -f './tests/run_make_tests'; then \
   echo "======|===$(which echo)"; \
   echo "======|===$(which tar)"; \
   echo "======|===$(which ulimit)"; \
   ulimit -n 128; \
   echo "======|===running ...."; \
else \
   echo "Can't find the GNU Make test suite (./tests)."; \
fi
======|===echo
======|===tar
======|===
make: (makefile:1559): failed to build 'check-regression' exit 1
make: (makefile:1284): failed to build 'check-am' exit 2
make: (makefile:1011): failed to build 'check-recursive' exit 1

Since ulimit cannot be found, ulimit -n 128; returns 1 and skips subsequent commands.

Subsequent commands continue to run when using gnu make. (Although still using busybox sh)

smalltalkman commented 4 months ago

Since ulimit cannot be found, ulimit -n 128; returns 1 and skips subsequent commands.

I was fooled by the which command, which does not reflect whether ulimit really exists. In fact ulimit is a shell builtin and can always be used.

Welcome to BusyBox v1.37.0-PRE-5323-g7e09f7ce4 (2024-04-09 12:55:52 BST) (MS/Windows 6.1 x86_64)  

ROOT: D:/gym/softwares/busybox                                                                    
HOME: D:/gym/softwares/busybox/home/root                                                          
TEMP: D:/gym/softwares/busybox/tmp                                                                

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# which echo; echo $?                                                                             
echo                                                                                              
0                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# which ulimit; echo $?                                                                           
1                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# type echo; echo $?                                                                              
echo is a shell builtin                                                                           
0                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# type ulimit; echo $?                                                                            
ulimit is a shell builtin                                                                         
0                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# ulimit; echo $?                                                                                 
1                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
# echo 999; echo $?                                                                               
999                                                                                               
0                                                                                                 

root@lenovo-PC C:/Users/lenovo/Desktop                                                            
#                                                                                                 

So the root of the problem is that the return result(1) of ulimit -n 128; causes subsequent commands to not be executed.

Also, should which ulimit truthfully reflect whether ulimit actually exists?

rmyorston commented 4 months ago

should which ulimit truthfully reflect whether ulimit actually exists?

which is intended to report the executable associated with a command. Since ulimit is a shell built-in it's quite correct to say nothing.

The type shell builtin can provide additional information:

$ type ulimit
ulimit is a shell builtin

At least, that's what you get on busybox-w32. On my Linux system ulimit is present as an executable and a shell builtin:

$ which ulimit
/usr/bin/ulimit
$ type ulimit
ulimit is a shell builtin
smalltalkman commented 4 months ago

which is intended to report the executable associated with a command. Since ulimit is a shell built-in it's quite correct to say nothing.

The type shell builtin can provide additional information:

$ type ulimit
ulimit is a shell builtin

Thank you for the explanation. I just don't know why the output of which echo is correct under busybox-w32, but which ulimit is not. However, it does not affect usage. So we can ignore it.

The problem I am currently facing is the same as https://github.com/rmyorston/busybox-w32/issues/409, the problem is that the return result(1) of ulimit -n 128; causes subsequent commands to not be executed.

rmyorston commented 4 months ago

I just don't know why the output of which echo is correct under busybox-w32, but which ulimit is not.

That's due to the shell in busybox-w32 being compiled in standalone shell mode, so all applets can be run from the shell even if they don't appear in PATH.

The shell help command lists this:

~ $ help
Built-in commands:
------------------
        . : [ [[ alias break cd chdir command continue echo eval exec
        exit export false getopts hash help history jobs kill let local
        printf pwd read readonly return set shift source test times title
        trap true type ulimit umask unalias unset wait [ [[ ar arch ascii
        ash awk base32 base64 basename bash bc bunzip2 busybox bzcat
        bzip2 cal cat cdrop chattr chmod cksum clear cmp comm cp cpio
        crc32 cut date dc dd df diff dirname dos2unix dpkg dpkg-deb drop
        du echo ed egrep env expand expr factor false fgrep find fold
        free fsync ftpget ftpput getopt grep groups gunzip gzip hd head
        hexdump httpd iconv id inotifyd install ipcalc jn kill killall
        lash less link ln logname ls lsattr lzcat lzma lzop lzopcat make
        man md5sum mkdir mktemp mv nc nl nproc od paste patch pdpmake
        pdrop pgrep pidof pipe_progress pkill printenv printf ps pwd
        readlink realpath reset rev rm rmdir rpm rpm2cpio sed seq sh
        sha1sum sha256sum sha3sum sha512sum shred shuf sleep sort split
        ssl_client stat strings su sum sync tac tail tar tee test time
        timeout touch tr true truncate ts tsort ttysize uname uncompress
        unexpand uniq unix2dos unlink unlzma unlzop unxz unzip uptime
        usleep uudecode uuencode vi watch wc wget which whoami whois
        xargs xxd xz xzcat yes zcat

The list of commands has two sections. From . to wait are shell builtins, while [ to zcat are applets.

Some shell builtins, like echo, are also applets, while others, like ulimit aren't.

which echo prints echo because it's an applet but doesn't print anything for which ulimit because it's only a shell builtin. The distinction is probably of little importance, but it does make which consistent with its behaviour in the non-standalone shell case.

I'm investigating the underlying problem.

avih commented 4 months ago

One could also use command -v NAME instead of which, e.g.:

if command -v ulimit >/dev/null; then
    echo has ulimit
else
    echo no ulimit
fi

This is POSIX behavior, and in the case of busybox-w32 would indicate that the shell can run ulimit.

How it interacts with make specifically I don't exactly know, but the fact that you can actually run ulimit from make (as far as I understand) suggests to me that using command should work in this use case.

smalltalkman commented 4 months ago

I'm investigating the underlying problem.

Thanks!

One could also use command -v NAME instead of which, This is POSIX behavior, and in the case of busybox-w32 would indicate that the shell can run ulimit.

Thank you, use command -v ulimit to check the problem better.

How it interacts with make specifically I don't exactly know, but the fact that you can actually run ulimit from make (as far as I understand) suggests to me that using command should work in this use case.

ulimit is indeed executed in the Makefile, but subsequent commands are not executed.

smalltalkman commented 4 months ago

It turns out that ulimit can be executed in busybox-w32 make. Although its return value causes subsequent commands to not be executed, this is off topic and maybe I should close the question. Thanks all @rmyorston @avih