Skip to content

Exception occurred in preexec_fn #70

@alexander-zhang

Description

@alexander-zhang

When setting memory_limit_MB to be not -1, we encounter exception:

{"status":"SandboxError","message":"exception on running command python /tmp/tmpmn1cjrq6/tmpzw8a2ydp.py: Exception occurred in preexec_fn. | None","compile_result":null,"run_result":{"status":"Error","execution_time":null,"return_code":null,"stdout":null,"stderr":"exception on running command python /tmp/tmpmn1cjrq6/tmpzw8a2ydp.py: Exception occurred in preexec_fn. | None"},"executor_pod_name":null,"files":{}}%

To determine the root cause, I put a try/except block inside the preexec_fn to catch the error.
We see:

2025-12-11 21:09:52 [debug    ] running command python /tmp/tmpvwksj3in/tmpy4x_jjk6.py [sandbox.runners.base]
/root/miniconda3/lib/python3.11/site-packages/structlog/stdlib.py:1087: UserWarning: Remove `format_exc_info` from your processor chain if you want pretty exceptions.
  ed = p(logger, meth_name, cast(EventDict, ed))
2025-12-11 21:09:52 [error    ] memory_limit_preexec failed    [sandbox.runners.base] error=current limit exceeds maximum limit error_type=ValueError
Traceback (most recent call last):
  File "/root/sandbox/sandbox/runners/base.py", line 136, in memory_limit_preexec
    resource.setrlimit(resource.RLIMIT_STACK, (soft_memory_limit, hard_memory_limit_STACK))
ValueError: current limit exceeds maximum limit
  File "/root/sandbox/sandbox/runners/base.py", line 58, in run_command_bare
    p = await asyncio.create_subprocess_shell(command,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/miniconda3/lib/python3.11/asyncio/subprocess.py", line 208, in create_subprocess_shell
    transport, protocol = await loop.subprocess_shell(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "uvloop/loop.pyx", line 2808, in subprocess_shell
  File "uvloop/loop.pyx", line 2778, in __subprocess_run
  File "uvloop/handles/process.pyx", line 611, in uvloop.loop.UVProcessTransport.new
  File "uvloop/handles/process.pyx", line 172, in uvloop.loop.UVProcess._init
2025-12-11 21:09:52 [warning  ] exception on running command python /tmp/tmpvwksj3in/tmpy4x_jjk6.py: Exception occurred in preexec_fn. | None [sandbox.runners.base]

The issue lies here:

if args.memory_limit_MB > 0:
def memory_limit_preexec():
_, hard_memory_limit_AS = resource.getrlimit(resource.RLIMIT_AS)
_, hard_memory_limit_DATA = resource.getrlimit(resource.RLIMIT_DATA)
soft_memory_limit = args.memory_limit_MB * 1024 * 1024
resource.setrlimit(resource.RLIMIT_AS, (soft_memory_limit, hard_memory_limit_AS))
resource.setrlimit(resource.RLIMIT_DATA, (soft_memory_limit, hard_memory_limit_DATA))
if platform.uname().system != "Darwin":
_, hard_memory_limit_STACK = resource.getrlimit(resource.RLIMIT_STACK)
resource.setrlimit(resource.RLIMIT_STACK, (soft_memory_limit, hard_memory_limit_STACK))
preexec_steps.insert(0, memory_limit_preexec)
preexec_fn = lambda: [step() for step in preexec_steps] if preexec_steps else None

It seems SandboxFusion tries to allocated the desired memory in the Address Space, Data, and Stack.

However, the Stack typically has a process-set maximum of much less than 1GB for example.
Therefore, exception is thrown due to an inability to update the Stack memory limit.

To fix this, I replaced:

def memory_limit_preexec():
                _, hard_memory_limit_AS = resource.getrlimit(resource.RLIMIT_AS)
                _, hard_memory_limit_DATA = resource.getrlimit(resource.RLIMIT_DATA)
                soft_memory_limit = args.memory_limit_MB * 1024 * 1024
                resource.setrlimit(resource.RLIMIT_AS, (soft_memory_limit, hard_memory_limit_AS))
                resource.setrlimit(resource.RLIMIT_DATA, (soft_memory_limit, hard_memory_limit_DATA))
                if platform.uname().system != "Darwin":
                    _, hard_memory_limit_STACK = resource.getrlimit(resource.RLIMIT_STACK)
                    resource.setrlimit(resource.RLIMIT_STACK, (soft_memory_limit, hard_memory_limit_STACK))

with

def memory_limit_preexec():
                try:
                    _, hard_memory_limit_AS = resource.getrlimit(resource.RLIMIT_AS)
                    _, hard_memory_limit_DATA = resource.getrlimit(resource.RLIMIT_DATA)
                    soft_memory_limit = args.memory_limit_MB * 1024 * 1024
                    resource.setrlimit(resource.RLIMIT_AS, (soft_memory_limit, hard_memory_limit_AS))
                    resource.setrlimit(resource.RLIMIT_DATA, (soft_memory_limit, hard_memory_limit_DATA))
                    if platform.uname().system != "Darwin":
                        _, hard_memory_limit_STACK = resource.getrlimit(resource.RLIMIT_STACK)
                        soft_stack_limit = min(soft_memory_limit, hard_memory_limit_STACK)
                        resource.setrlimit(resource.RLIMIT_STACK, (soft_stack_limit, hard_memory_limit_STACK))
                except Exception as e:
                    logger.error(
                        "memory_limit_preexec failed",
                        error_type=type(e).__name__,
                        error=str(e),
                        exc_info=True,
                    )
                    raise

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions