Coordinate Basic Threads and Inspect Them on Linux
Company: Coreweave
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
Explain how to invoke a supplied function concurrently using basic thread APIs, manage the threads' lifecycle, and inspect the process's threads on Linux. Higher-level process pools, thread pools, and `asyncio` are not allowed for this exercise.
### Constraints & Assumptions
- The source permits Python or C++ and specifically names basic threading APIs. Use Python's `threading` primitives for this practice version; do not use `ProcessPoolExecutor`, `ThreadPoolExecutor`, or `asyncio`.
- **Practice scope:** a finite list of independent work items is supplied to a callable. Invoke it once for each item, use a bounded number of manually created worker threads, retain a result or exception for each input position, and wait for all started threads before returning.
- The source does not reveal the callable's behavior or the later interview parts. Do not invent those requirements.
- Clarify whether the callable is thread-safe, whether it blocks on I/O, and whether concurrent invocation is permitted. Do not assume threads always speed up CPU-bound Python code.
### Clarifying Questions to Ask
- Can two calls share or mutate state, and which component is responsible for synchronization?
- Should one failed call stop future work or should the remaining items continue?
- Are results required in input order or completion order?
- Can the callable cooperate with cancellation, and can a call block indefinitely?
### Part 1 — Coordinate Basic Threads
Describe thread creation, work assignment, result collection, and joining for the practice scope. Explain which shared state needs synchronization and what happens when a call raises an exception.
#### What This Part Should Cover
- Bounded manual `Thread` creation and exactly-once assignment of input positions within one invocation.
- Short critical sections around shared coordination, with the supplied function called outside the assignment lock.
- Explicit exception capture, deterministic result indexing, and joining non-daemon workers.
### Part 2 — Inspect Threads on Linux
Give commands that list a process's threads and show per-thread activity. Explain how to relate operating-system thread IDs to application diagnostics and distinguish observation from proof of correctness.
#### What This Part Should Cover
- Process ID versus Linux thread ID, and suitable thread-list or live-inspection commands.
- Native thread identity and names in application logs.
- The limits of CPU usage and thread-state snapshots when diagnosing deadlock, waiting, or a slow callable.
```hint Do not serialize the expensive work
A lock can protect assignment of the next input index without remaining held while the supplied function runs.
```
### What a Strong Answer Covers
- Correct use of basic threading primitives under the stated library restrictions.
- No skipped or multiply assigned work items, lost exceptions, or forgotten joins.
- Realistic discussion of Python parallelism and cooperative shutdown.
- Linux diagnostics that identify the actual threads involved without treating one snapshot as a full concurrency analysis.
### Follow-up Questions
- What changes if the callable mutates a shared non-thread-safe object?
- Why does a timeout on `join` not stop the corresponding thread?
- How would you report partial completion if a cooperative cancellation request arrives midway through the input list?
Overview: Use basic Python threading primitives for bounded concurrent function calls, exception capture and joining, then inspect native threads with Linux tools.