Last active
July 15, 2016 10:18
-
-
Save epipping/393f1c5d5fe388a4c7903b53e4e416ff to your computer and use it in GitHub Desktop.
Test how ulimit behaves on your OS (with different shells)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
get_sigcode() { | |
/bin/kill -l | | |
awk -v name=$1 ' | |
BEGIN { nf = 0 } | |
{ | |
for (i=1; i<=NF; ++i) | |
if (toupper($i) == name) | |
print i+nf; | |
nf += NF | |
}' | |
} | |
create_runner() { | |
cat > sig.c <<'EOF' | |
#include <stdlib.h> | |
#include <stdio.h> | |
int | |
main() | |
{ | |
int runs = 0; | |
double x = 0.0; | |
for (;;runs++) { | |
x += (double)rand() / RAND_MAX; | |
if (x >= 1e7) { | |
printf("Took %d iterations to reach 1000.\n", runs); | |
x = 0.0; | |
runs = 0; | |
} | |
} | |
return 0; | |
} | |
EOF | |
cc sig.c -o sig | |
rm -f sig.c | |
echo Successfully compiled sig.c | |
} | |
create_counter() { | |
cat > sigcnt.c <<'EOF' | |
#include <stdatomic.h> | |
#include <signal.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <time.h> | |
sig_atomic_t sig_received; | |
void handle_signal(int signum) { | |
sig_received = signum; | |
} | |
int | |
main() | |
{ | |
signal(SIGXCPU, handle_signal); | |
int sigxcpu_cnt = 0; | |
time_t start, now; | |
time(&start); | |
int runs = 0; | |
double x = 1; | |
for (;;) { | |
if (sig_received == SIGXCPU) { | |
sigxcpu_cnt++; | |
sig_received = 0; | |
} | |
time(&now); | |
if (now - start > 5) { | |
switch (sigxcpu_cnt) { | |
case 0: | |
fprintf(stderr, "none\n"); | |
exit(0); | |
case 1: | |
fprintf(stderr, "one\n"); | |
exit(0); | |
default: | |
fprintf(stderr, "multiple\n"); | |
exit(0); | |
} | |
} | |
// Do something random that eats CPU (sleeping is not an option) | |
x += (double)rand() / RAND_MAX; | |
if (x >= 1e7) { | |
printf("Took %d iterations to reach 1000.\n", runs); | |
x = 0.0; | |
runs = 0; | |
} | |
} | |
} | |
EOF | |
cc sigcnt.c -o sigcnt | |
rm -f sigcnt.c | |
echo Successfully compiled sigcnt.c | |
} | |
echo_underscored() { | |
out1=$1 | |
out2='' | |
for ((i=0; i < ${#out1}; ++i)); do | |
out2+='=' | |
done | |
echo $out1 | |
echo $out2 | |
} | |
test_shell() { | |
shell=$1 | |
echo_underscored "Testing shell: $shell" | |
f() { | |
$shell -c 'ulimit -St 3; ulimit -t 2; ulimit -Ht; ulimit -St' | tr -d '\n' | |
} | |
case `f` in | |
22) | |
t_sets='both limits';; | |
unlimited2) | |
t_sets='soft limit';; | |
*) | |
echo UNEXPECTED;; | |
esac | |
echo "ulimit -t sets: ${t_sets}" | |
f() { | |
$shell -c 'ulimit -St 3; ulimit -Ht 4; ulimit -St 3; ulimit -t' | |
} | |
case `f` in | |
3) | |
t_gets='soft limit';; | |
*) | |
echo UNEXPECTED;; | |
esac | |
echo "ulimit -t gets: ${t_gets}" | |
f() { | |
$shell -c 'ulimit -St 2; ulimit -Ht 1' >/dev/null 2>&1 && | |
echo yes || echo no | |
} | |
ht_can_set_below_soft=`f` | |
echo "Hard limits can be set below the soft limit: ${ht_can_set_below_soft}" | |
f() { | |
$shell -c 'ulimit -St 1; ulimit -Ht 2; ulimit -St 3' >/dev/null 2>&1 && | |
echo yes || echo no | |
} | |
st_can_set_above_hard=`f` | |
echo "Soft limits can be set above the hard limit: ${st_can_set_above_hard}" | |
f() { | |
$shell -c 'ulimit -St 1; ulimit -Ht 2; ulimit -Ht 3' >/dev/null 2>&1 && | |
echo yes || echo no | |
} | |
hard_can_be_raised=`f` | |
echo "Hard limits can be raised without privileges: ${hard_can_be_raised}" | |
f() { | |
$shell -c 'ulimit -St 1; ./sig' >/dev/null 2>&1 | |
echo $? | |
} | |
case $((`f` - 128)) in | |
${sigxcpu}) | |
soft_signal=SIGXCPU;; | |
${sigkill}) | |
soft_signal=SIGKILL;; | |
*) | |
echo UNEXPECTED; | |
esac | |
echo "soft signal: ${soft_signal}" | |
f() { | |
$shell -c 'ulimit -St 1; ulimit -Ht 1; ./sig' >/dev/null 2>&1 | |
echo $? | |
} | |
case $((`f` - 128)) in | |
${sigxcpu}) | |
hard_signal=SIGXCPU;; | |
${sigkill}) | |
hard_signal=SIGKILL;; | |
*) | |
echo UNEXPECTED;; | |
esac | |
echo "hard signal: ${hard_signal}" | |
f() { | |
$shell -c 'ulimit -St 1; ./sigcnt 2>&1 >/dev/null' | |
} | |
sigxcpus_sent=`f` | |
echo "Number of SIGXCPUs sent: ${sigxcpus_sent}" | |
} | |
test_shell_sudo() { | |
shell=$1 | |
echo_underscored "Testing shell with sudo: $shell" | |
f() { | |
sudo $shell -c 'ulimit -St 1; ulimit -Ht 1; ulimit -St 2 && ulimit -Ht' \ | |
2>/dev/null; | |
} | |
out=`f`; ret=$?; | |
if [[ $ret == 0 ]]; then | |
case $out in | |
1) | |
raising_soft_beyond_hard='no';; | |
2) | |
raising_soft_beyond_hard='yes';; | |
*) | |
echo UNEXPECTED;; | |
esac | |
else | |
raising_soft_beyond_hard='impossible' | |
fi | |
echo "Raising soft beyond hard limit raises it: ${raising_soft_beyond_hard}" | |
} | |
main() { | |
echo "Testing on platform: $(uname)" | |
sigxcpu=$(get_sigcode XCPU) | |
sigkill=$(get_sigcode KILL) | |
echo Number of signal SIGXCPU: ${sigxcpu} | |
echo Number of signal SIGKILL: ${sigkill} | |
create_runner | |
create_counter | |
echo | |
for shell in zsh bash dash; do | |
which $shell >/dev/null || continue; | |
test_shell $shell | |
echo | |
done | |
for shell in zsh bash dash; do | |
which $shell >/dev/null || continue; | |
test_shell_sudo $shell | |
echo | |
done | |
} | |
main |
Author
epipping
commented
Jun 15, 2016
Darwin/zsh | Darwin/bash | FreeBSD/zsh | FreeBSD/bash | FreeBSD/dash | Linux/zsh | Linux/bash | Linux/dash | |
ulimit -t sets | soft limit | both limits | soft limit | both limits | both limits | soft limit | both limits | both limits |
ulimit -t gets | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit |
Hard limits can be set below the soft limit | yes | no | yes | yes | yes | yes | no | no |
Soft limits can be set above the hard limit | yes | no | yes | no | no | yes | no | no |
Hard limits can be raised without privileges | yes | no | yes | no | no | yes | no | no |
soft signal | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU |
hard signal | SIGXCPU | SIGXCPU | SIGKILL | SIGKILL | SIGKILL | SIGKILL | SIGKILL | SIGKILL |
Number of SIGXCPUs sent | one | one | one | one | one | multiple | multiple | multiple |
Raising soft beyond hard limit raises it | yes | impossible* | yes | no | no | yes | impossible* | impossible* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment