
编程学习工具的资源边界在线编程练习看起来只是“编辑代码点击运行”后台却要接收不可信源码、准备编译环境、执行程序再把输出送回编辑器。任何一步没有边界都可能让一个死循环拖住工作节点或让一份恶意代码读到别人的文件。学习工具既要让学生自由试错也要保证一次试错不会影响其他人。每次运行都是独立任务代码提交后应立即生成任务标识并绑定编辑器会话与用户。后续的编译日志、运行结果和取消操作都沿着同一条关联关系传递request_id - editor_id - result这个关系不能只存在于前端内存。用户刷新页面、网络重连或同时打开两个编辑器时旧结果可能晚于新结果返回。前端收到消息后要核对request_id只把结果写回对应的编辑器。服务端也要区分“任务已接收”“正在编译”“正在运行”“已取消”和“已结束”避免超时后仍把后台完成的结果当成当前任务。每次执行使用干净的工作目录目录中只放本次源码和明确提供的测试数据。编译缓存可以共享但缓存键必须包含语言版本、依赖版本和编译参数缓存内容也不能带入用户文件。任务结束后清理临时目录清理失败要有记录和补偿机制而不是等磁盘写满才发现。限制 CPU、内存、进程和输出运行超时只是最基本的一条线。学生代码可以快速派生大量子进程、持续申请内存、打开文件描述符或不断向标准输出写数据。执行环境需要同时限制 CPU 时间、内存、进程数、打开文件数、磁盘空间和输出大小。到达上限时平台应结束整个进程组不能只杀掉最外层的解释器。错误信息要适合学习场景。与其返回“系统异常”不如区分编译失败、运行超时、内存超限和输出超限并保留学生能够理解的日志片段。底层宿主机路径、容器标识和内部调用栈则不应暴露。若日志被截断要明确提示截断位置否则学生可能误以为程序只输出了这些内容。不同语言的资源特征不同。编译型语言启动阶段可能占用较多内存脚本语言更容易在运行阶段形成无界循环。配额应按语言和题目类型配置不能为了某个特殊题目把所有任务的上限一起放大。确实需要长时间运行的练习可以进入单独队列或专用执行池。网络与文件权限默认关闭多数基础练习不需要访问公网也不需要读取宿主机文件。执行环境应默认断网、使用非特权身份、挂载只读运行时并只开放本次工作目录的写入。需要下载依赖的课程应在构建阶段准备受控依赖或通过带白名单和缓存的代理完成不能让学生代码任意请求外部地址。判题数据也要与学生可见文件分开。程序可以通过规定接口读取输入但不应列出隐藏用例或其他用户提交。多租户平台还要验证符号链接、路径穿越、异常文件名和压缩包解压等入口防止工作目录限制被绕过。高峰期先保护已在运行的任务上课或比赛开始时提交会集中到达。入口队列必须有长度和等待时间上限达到上限后直接告诉用户“当前繁忙可稍后重试”比让所有任务排队到超时更诚实。调度器可以按用户限制并发避免一个人连续点击运行占满执行槽已经开始的任务则保留必要资源减少频繁抢占造成的重复编译。验收时应准备死循环、内存持续增长、子进程逃逸、超量输出、网络访问和磁盘写满等样例同时测试取消和页面重连。资源边界是否有效不看正常代码跑得多快而看这些异常任务结束后执行节点能否迅速恢复其他学生的任务是否仍能按预期完成。