NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ulimit -d/-m do not actually work



On Tue, Oct 22, 2024 at 09:28:01AM -0400, Greg Troxel wrote:
> I suspect that "ulimit -d" does not work correctly, so I wrote a test
> program, which simply allocates 4K chunks and writes an int into each.
> It keeps a count, and prints the amount it was able to allocate in kB.
> 
> (Yes, I know there's malloc overhead and other things; the point is just
> to see if limits are working at get a feeling for the malloc overhead
> and other data, to sanity check using limits in a program that's too
> complicated to understand 100% reliably.)
> 
> The tests below are on reasonably recent netbsd-10 amd64, that has 32G
> of RAM.
> 
> I limited the test program to 4GB (to avoid provoking unrelated zfs
> locking bugs I've written about before).
> 
> Running it with my default limits:
> 
>   number of threads                   (-T) 8192
>   socket buffer size           (bytes, -b) unlimited
>   core file size              (blocks, -c) unlimited
>   data seg size               (kbytes, -d) 8388608
>   file size                   (blocks, -f) unlimited
>   max locked memory           (kbytes, -l) 10740156
>   max memory size             (kbytes, -m) 32220468
>   open files                          (-n) 20000
>   pipe size                (512 bytes, -p) 1
>   stack size                  (kbytes, -s) 4096
>   cpu time                   (seconds, -t) unlimited
>   max user processes                  (-u) 1044
>   virtual memory              (kbytes, -v) unlimited
> 
> got me
> 
>   4194304
> 
> I didn't want to mess up my shell's limits, so I started a new /bin/sh,
> and reduced the data limit to 1024 and the memory limit to 1024.  The
> unit is kB, so this is a mere 1MB of memory.  Which is plenty to run the
> test program:
> 
>    text    data     bss     dec     hex filename
>    2600     578      72    3250     cb2 test-data
> 
> But, I still can allocate 4GB:
> 
>   $ ulimit -a
>   time          (-t seconds    )    unlimited
>   file          (-f blocks     )    unlimited
>   data          (-d kbytes     )      8388608
>   stack         (-s kbytes     )         4096
>   coredump      (-c blocks     )    unlimited
>   memory        (-m kbytes     )     32220468
>   locked memory (-l kbytes     )     10740156
>   thread        (-r threads    )         8192
>   process       (-p processes  )         1044
>   nofiles       (-n descriptors)        20000
>   vmemory       (-v kbytes     )    unlimited
>   sbsize        (-b bytes      )    unlimited
>   $ ulimit -d 1024
>   $ ulimit -a 
>   time          (-t seconds    )    unlimited
>   file          (-f blocks     )    unlimited
>   data          (-d kbytes     )         1024
>   stack         (-s kbytes     )         4096
>   coredump      (-c blocks     )    unlimited
>   memory        (-m kbytes     )     32220468
>   locked memory (-l kbytes     )     10740156
>   thread        (-r threads    )         8192
>   process       (-p processes  )         1044
>   nofiles       (-n descriptors)        20000
>   vmemory       (-v kbytes     )    unlimited
>   sbsize        (-b bytes      )    unlimited
>   $ ./test-data
>   4194304
>   $ ulimit -m 1024
>   $ ulimit -a
>   time          (-t seconds    )    unlimited
>   file          (-f blocks     )    unlimited
>   data          (-d kbytes     )         1024
>   stack         (-s kbytes     )         4096
>   coredump      (-c blocks     )    unlimited
>   memory        (-m kbytes     )         1024
>   locked memory (-l kbytes     )     10740156
>   thread        (-r threads    )         8192
>   process       (-p processes  )         1044
>   nofiles       (-n descriptors)        20000
>   vmemory       (-v kbytes     )    unlimited
>   sbsize        (-b bytes      )    unlimited
>   $ ./test-data
>   4194304
> 
> Questioning my program, I ran top in another window and saw "4067M" in
> the RSS column.
> 
> Yet in that shell in that state, "unison" fails:
> 
>     $ unison
>     sh: unison: not enough memory
> 
> So it seems NetBSD won't exec a process that would exceed the limit at
> exec time, but malloc is able to obtain virtual memory (which is backed
> by actual memory) that is not constrained.
> 
> background (skippable):
> 
>   I am trying to test unison (a file sync tool), to find out how much
>   memory it needs for various workloads.  I wrote a script to set limits
>   via ulimit(1), both data and stack, sticking to POSIX, and invoked
>   unison.  I then did binary search manually, to find the smallest
>   limits that worked.
> 
>   For stack, it was 88, 100, and 212, for 10000, 20000, and 40000 files.
>   That wasn't really surprising.
> 
>   For data, it was 1376.  That's kB, and it didn't seem remarkable.
>   But, it was the same for varying workloads.
> 
> 
> ----------------------------------------
> /*
>  * test-data.c: Test data size limit. 
>  * Allocate memory until failure.
>  * Print amount allocated.
>  */
> 
> #include <stdio.h>
> #include <stdlib.h>
> 
> #define BUFSIZK	4
> 
> int
> main(int argc, char **argv)
> {
>   int i;
>   int *buf;
> 
>   /*
>    * Limit to 4 GB, to avoid problems if data segment limits are not
>    * working as expected.
>    */
>   for (i = 0; i < (4 * 1024 * 1024) / BUFSIZK; i++) {
>     /* Allocate, write to force a page, and discard. */
>     buf = malloc(BUFSIZK * 1024);
>     if (buf == NULL)
>       break;
>     buf[0] = 0;
>     buf = NULL;
>   }
> 
>   /* Print in kB. */
>   printf("%d\n", i * BUFSIZK);
> }

This is normal with modern anonymous memory allocations for malloc.


Home | Main Index | Thread Index | Old Index