Polyman Documentation - v2.2.2
    Preparing search index...

    Class CommandExecutor

    Command executor for running external programs with resource constraints. Manages process lifecycle, timeout enforcement, memory limits, and cleanup. Supports cross-platform execution (Unix/Windows) with platform-specific optimizations.

    CommandExecutor

    import { executor } from './executor';

    const result = await executor.execute('./solution', {
    timeout: 2000,
    memoryLimitMB: 256,
    silent: false
    });
    Index

    Constructors

    Properties

    tempFiles: string[] = []
    activeProcesses: Set<ChildProcess> = ...

    Methods

    • Execute a shell command with timeout and memory limits. Automatically kills the process if it exceeds time or memory constraints.

      Parameters

      • command: string

        Shell command to execute

      • options: ExecutionOptions

        Execution configuration

      Returns Promise<ExecutionResult>

      Execution result with stdout, stderr, and status

      If command fails and no onError callback is provided

      If timeout occurs and no onTimeout callback is provided

      If memory limit exceeded and no onMemoryExceeded callback is provided

      // Run a C++ solution
      const result = await executor.execute('./solution', {
      timeout: 1000,
      memoryLimitMB: 256
      });
      // With error handling
      const result = await executor.execute('./buggy_solution', {
      timeout: 2000,
      onError: (result) => console.log('Solution failed:', result.stderr),
      onTimeout: (result) => console.log('TLE')
      });
    • Private

      Applies memory limit to a command using platform-specific methods. For Java programs, uses -Xmx flag. For Unix, uses ulimit. Windows memory limits are not fully supported.

      Parameters

      • command: string

        Command to wrap with memory limit

      • OptionalmemoryLimitMB: number

        Memory limit in megabytes

      Returns string

      Command wrapped with memory limit enforcement

      // Java command
      applyMemoryLimit('java Solution', 256)
      // Returns: 'java -Xmx256m Solution'
      // C++ command on Unix
      applyMemoryLimit('./solution', 256)
      // Returns: '(ulimit -v 262144; ./solution)'
    • Private

      Normalizes command syntax for the current platform.

      • On Windows, converts './foo' to '.\foo' and forward slashes in the executable path to backslashes to avoid ERROR_PATH_NOT_FOUND (3).
      • Leaves arguments and redirections intact.

      Parameters

      • command: string

        Command line string to normalize

      Returns string

      Normalized command string appropriate for the platform

    • Private

      Spawns a child process for command execution. Creates a detached process in shell mode to allow process tree management. Registers process in active processes set for cleanup tracking.

      Parameters

      • command: string

        Shell command to spawn

      • options: ExecutionOptions

        Execution options including cwd

      Returns { process: ChildProcessWithoutNullStreams; result: ExecutionResult }

      Spawned process and empty result object

      const { process, result } = this.spawnProcess('./solution', { timeout: 1000 });
      
    • Private

      Creates an empty execution result object with default values. Used as initial state before process execution completes.

      Returns ExecutionResult

      Empty result with default values

      const result = this.createEmptyResult();
      // Returns: { stdout: '', stderr: '', exitCode: 0, success: false, ... }
    • Private

      Creates output collectors for stdout and stderr streams. Attaches data event handlers to accumulate process output. Tracks whether the result has been resolved to prevent race conditions.

      Parameters

      • child: ChildProcess

        Child process to collect output from

      Returns { stdout: string; stderr: string; isResolved: boolean }

      Output collectors object

      const collectors = this.createOutputCollectors(child);
      // collectors.stdout and collectors.stderr accumulate as process runs
    • Private

      Creates a cancellable delay promise for timeout implementation. Returns both the timeout promise and a cancel function. Cancel function clears the timeout to prevent unnecessary process kills.

      Parameters

      • ms: number

        Delay duration in milliseconds

      Returns [Promise<void>, () => void]

      Tuple of [timeout promise, cancel function]

      const [timeoutPromise, cancelTimeout] = this.cancellableDelay(1000);
      timeoutPromise.then(() => console.log('Timed out'));
      // Later, if process finishes early:
      cancelTimeout();
    • Private

      Handles timeout scenario when process exceeds time limit. Kills the process tree, updates result with timeout status, and invokes callbacks. Uses SIGKILL after grace period to ensure process termination.

      Parameters

      • child: ChildProcess

        Process that timed out

      • options: ExecutionOptions

        Execution options with timeout callback

      • result: ExecutionResult

        Result object to update

      • collectors: { stdout: string; stderr: string; isResolved: boolean }

        Output collectors

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called internally when timeout occurs
      this.handleTimeout(child, options, result, collectors, resolve, reject);
    • Private

      Attaches event handlers for process lifecycle events (close, error). Handles process completion, cleanup, and error scenarios. Ensures timeout is cancelled when process ends naturally.

      Parameters

      • child: ChildProcess

        Child process to attach handlers to

      • options: ExecutionOptions

        Execution options

      • result: ExecutionResult

        Result object to populate

      • collectors: { stdout: string; stderr: string; isResolved: boolean }

        Output collectors

      • cancelTimeout: () => void

        Function to cancel timeout

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called internally during execute()
      this.attachEventHandlers(child, options, result, collectors, cancelTimeout, resolve, reject);
    • Private

      Handles process close event and determines outcome. Routes to appropriate handler based on exit code and signals. Checks for memory errors, success (code 0), or general errors.

      Parameters

      • code: number | null

        Process exit code

      • signal: Signals | null

        Process termination signal

      • options: ExecutionOptions

        Execution options

      • result: ExecutionResult

        Result object to populate

      • collectors: { stdout: string; stderr: string }

        Output collectors

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called internally by close event handler
      this.handleProcessClose(0, null, options, result, collectors, resolve, reject);
    • Private

      Detects if process failed due to memory issues. Checks both exit codes (137, SIGABRT) and error messages in stderr. Recognizes common memory error patterns across languages.

      Parameters

      • code: number | null

        Process exit code

      • signal: Signals | null

        Process termination signal

      • stderr: string

        Standard error output

      Returns boolean

      True if memory error detected

      // Exit code 137 indicates OOM kill
      this.isMemoryError(137, null, '') // returns true
      // C++ bad_alloc exception
      this.isMemoryError(1, null, 'terminate called after throwing bad_alloc') // returns true
    • Private

      Handles memory limit exceeded scenario. Updates result with MLE status and invokes appropriate callback. Displays warning unless silent mode is enabled.

      Parameters

      • code: number | null

        Process exit code

      • signal: Signals | null

        Process termination signal

      • options: ExecutionOptions

        Execution options with MLE callback

      • result: ExecutionResult

        Result object to update

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called when OOM detected
      this.handleMemoryError(137, null, options, result, resolve, reject);
    • Private

      Handles successful process execution (exit code 0). Updates result status, displays output unless silent, and invokes success callback.

      Parameters

      Returns void

      // Called when process exits with code 0
      this.handleSuccess(options, result, resolve);
    • Private

      Handles failed process execution (non-zero exit code). Updates result status, displays error unless silent, and invokes error callback or rejects.

      Parameters

      • options: ExecutionOptions

        Execution options with error callback

      • result: ExecutionResult

        Result object to update

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called when process exits with non-zero code
      this.handleError(options, result, resolve, reject);
    • Private

      Handles process spawn errors (e.g., command not found, permission denied). Updates result with error information and invokes error callback or rejects.

      Parameters

      • err: Error

        Error from process spawn

      • options: ExecutionOptions

        Execution options with error callback

      • result: ExecutionResult

        Result object to update

      • resolve: (value: ExecutionResult) => void

        Promise resolve function

      • reject: (reason?: unknown) => void

        Promise reject function

      Returns void

      // Called when spawn() throws error
      this.handleProcessError(new Error('ENOENT'), options, result, resolve, reject);
    • Private

      Kills a process and its entire child process tree. Uses platform-specific methods: taskkill on Windows, process groups on Unix. Attempts to kill process group first, falls back to single process.

      Parameters

      • pid: number

        Process ID to kill

      Returns void

      // Kill process tree on Unix
      this.killProcessTree(12345);
      // Sends SIGKILL to -12345 (process group)
      // Kill process tree on Windows
      this.killProcessTree(12345);
      // Runs: taskkill /pid 12345 /T /F
    • Execute a command with input/output file redirection. Wraps the execute method with automatic stdin/stdout redirection.

      Parameters

      • command: string

        Shell command to execute

      • options: ExecutionOptions

        Execution configuration

      • OptionalinputFile: string

        Path to file for stdin redirection (optional)

      • OptionaloutputFile: string

        Path to file for stdout redirection (optional)

      Returns Promise<ExecutionResult>

      Execution result

      // Run solution with test input and capture output
      await executor.executeWithRedirect(
      './solution',
      { timeout: 1000 },
      'tests/test1.txt',
      'output.txt'
      );
    • Private

      Builds a shell command with input/output redirection. Appends stdin (<) and stdout (>) redirections as needed.

      Parameters

      • command: string

        Base command to execute

      • OptionalinputFile: string

        Optional input file path for stdin

      • OptionaloutputFile: string

        Optional output file path for stdout

      Returns string

      Command with redirection operators

      buildRedirectedCommand('./solution', 'input.txt', 'output.txt')
      // Returns: './solution < input.txt > output.txt'
      buildRedirectedCommand('./solution', 'input.txt')
      // Returns: './solution < input.txt'
    • Register a temporary file for tracking. Useful for cleanup operations after execution completes.

      Parameters

      • filePath: string

        Path to the temporary file

      Returns void

      executor.registerTempFile('/tmp/test_output.txt');
      
    • Clean up all active processes and clear temp file registry. Kills any running processes and resets internal state. Should be called when shutting down or after batch operations. On Windows, waits for file handles to be released.

      Returns Promise<void>

      Resolves when cleanup is complete

      try {
      await runAllTests();
      } finally {
      await executor.cleanup();
      }
    • Private

      Kills all currently active processes tracked by the executor. Iterates through active processes set and kills each process tree. Used during cleanup or shutdown operations.

      Returns void

      // Called by cleanup() method
      this.killAllActiveProcesses();
    • Get a copy of the registered temporary files list.

      Returns string[]

      Array of temporary file paths

      const tempFiles = executor.getTempFiles();
      tempFiles.forEach(file => fs.unlinkSync(file));