تصور کنید هر بار که کلید Enter را میزنید، باید ۱۵.۶ ثانیه به صفحه نمایش خیره شوید تا اولین بایت پاسخ ظاهر شود. این کابوس برای برخی از کاربران Codex در محیط ویندوز به واقعیت تبدیل شده است؛ تأخیری که نه از کندی پاسخهای هوش مصنوعی است و نه ناشی از لگهای شبکه، بلکه یک «سکوت مطلق» بین فشردن کلید Enter و شروع اولین عملیات است. این مشکل تنها به دلیل یک کاراکتر بکاسلش اشتباه در CLI ایجنت ویندوز رخ میدهد.
برای توسعهدهندگانی که به سرعت در محیط ترمینال عادت کردهاند، این نوع باگها — که ما آنها را باگهای «حسی» یا Vibe-based مینامیم — یک کابوس واقعی هستند؛ زیرا اغلب در محیطهای پاک و استاندارد ناپدید میشوند. برای مثال، در یک ماشین مجازی (VM) استاندارد، ممکن است دستور فوراً با خطا مواجه شود و سریع بازگردد. اما در یک ایستگاه کاری واقعی که نرمافزارهای امنیتی روی آن نصب است، این باگ به یک سیاهچاله برای بهرهوری تبدیل میشود.
این مسئله که در مخزن openai/codex (مورد شماره ۴۱۳۵۱) ردیابی میشود، تلاقی خطرناکی بین زبانهای برنامهنویسی مدرن و رفتارهای قدیمی API ویندوز را برجسته میکند. این مورد نشان میدهد که چگونه یک خطای کوچک در نحو (Syntax) میتواند زنجیرهای از واکنشهای کندکننده را در هسته (Kernel) سیستمعامل ویندوز فعال کند. در حالی که برخی ابزارها تلاش میکنند تأخیرهای امنیتی عاملهای هوش مصنوعی را به حد میکروثانیه برسانند، چنین خطاهای سیستمی میتوانند تمام این بهینهسازیها را بیاثر کنند.
کالبدشکافی توقف (The Anatomy of the Stall)
این تأخیر از نحوه مدیریت مسیرهای دستگاه (Device Paths) در ویندوز ناشی میشود. در کد منبع codex-rs، بهطور مشخص در فایل windows-sandbox-rs/src/acl.rs و در تابع allow_null_device()، برنامه سعی میکند دستگاه NUL را باز کند.
به جای استفاده از مسیر صحیح \.\NUL (که در آن دو بکاسلش اول برای شروع مسیر دستگاه هستند)، برنامهنویس از یک رشته خام (Raw String) در زبان Rust استفاده کرده است: r"\\.\NUL". از آنجایی که رشتههای خام در Rust کاراکترهای فرار (Escape) را پردازش نمیکنند، بایتهای نهایی تولید شده به صورت لیتراسی (Literal) هستند: چهار بکاسلش در ابتدا، یک نقطه و دو بکاسلش دیگر.
ویندوز هر مسیری که با دو بکاسلش شروع شود را به عنوان یک نام UNC (Universal Naming Convention) تفسیر میکند. در نتیجه، سیستم به جای باز کردن یک دستگاه محلی، تصور میکند که باید به دنبال سروری در شبکه به نام "NUL" بگردد.
معناشناسی مسیرها و قوانین ویندوز
برای درک دلیل این شکست، باید به قوانین مایکروسافت در مورد نامگذاری فایلها، مسیرها و فضای نامها (Namespaces) نگاه کرد. رفتار سیستم بر اساس پیشوند مسیر به شدت تغییر میکند:
- NUL: یک نام دستگاه رزرو شده است که در هر دایرکتوری کار میکند (به همین دلیل دستور
> NULاز هر جایی اجرا میشود). - \.\NUL: از فضای نام دستگاه Win32 استفاده میکند. این روش صریح و صحیح برای باز کردن یک دستگاه است.
- \NUL: این یک مسیر دستگاه نیست. چون با دو بکاسلش شروع میشود، ویندوز آن را به زنجیره تامینکنندگان شبکه (شامل
LanmanWorkstationوmrxsmb) هدایت میکند تا سروری به نام "NUL" را پیدا کند. - \?\C:...: پیشوند طول گسترده (Extended-length). این پیشوند به لایه API میگوید که از تجزیه و تحلیل رشته (String Parsing) و نرمالسازی صرفنظر کند و ترجمه نام دستگاه را غیرفعال نماید.
سقوط عملکردی (The Performance Cliff)
وقتی ابزار CLI تابع CreateFileW را با این مسیر بدشکل فراخوانی میکند، توالی خاصی از اتفاقات رخ میدهد. بررسی Stack Trace مسیر زیر را فاش میکند: CreateFileW $\rightarrow$ GetDriveTypeW $\rightarrow$ ZwCreateFile $\rightarrow$ FLTMGR.SYS.
- درخواست ابتدا به
GetDriveTypeWمیرسد؛ تابعی که به دلیل مسدود شدن (Block) طولانیمدت در مواجهه با مسیرهایی که نمیتواند طبقهبندی کند، معروف است. - ویندوز درخواست را به لایه تامینکننده شبکه میفرستد تا بپرسد این مسیر به چه نوع درایوی اشاره دارد.
- در مورد مسیرهای UNC در دسترس نبودن، این فراخوانی میتواند باعث هنگ کردن سیستم شود. این یک خطر شناخته شده است؛ برای مثال، مورد شماره ۸۸۵۹ در wxWidgets مربوط به سال ۲۰۰۷ نشان داد که
wxFSVolumeبه مدت یک دقیقه روی یک مسیر\\server\driveدر دسترس نبود، زیراFilteredAddتابعGetDriveTypeرا فراخوانی کرده بود. - برخلاف در دسترس بودن حروف درایو (Drive-letter)، مسیرهای UNC کش (Cache) نمیشوند، به این معنی که سیستم در هر بار فراخوانی مجدداً متوقف میشود.
در یک ماشین ویندوز ۱۱ پاک، این عملیات در میکروثانیه شکست میخورد. مسیر \\NUL از GetFullPath بیرون میافتد، CreateFileW در کمتر از یک میلیثانیه خطای ۱۶۱ (ERROR_BAD_PATHNAME) را برمیگرداند و GetDriveTypeW به سادگی مقدار DRIVE_NO_ROOT_DIR را باز میگرداند.
با این حال، برای کاربر گزارشدهنده، یک درایور فیلتر سیستمفایل شخص ثالث به نام 360FsFlt.sys در مسیر این فراخوانی شکستخورده قرار دارد و تأخیری عظیم ۱۵.۴ ثانیهای را اضافه میکند. این دقیقاً توضیح میدهد که چرا جستجو برای این باگ سخت است: در یک VM پاک سریع است، اما در یک سیستم واقعی ویرانگر.
اندازهگیری اثرات
دادههای استخراجشده از مورد Codex یک شکاف عملکردی تکاندهنده را بر اساس تنظیمات Sandbox نشان میدهد. در یک محیط Sandbox ویندوز بدون دسترسی بالا (Unelevated)، شروع دستورات تقریباً ۱۵.۶ ثانیه طول میکشید. اما وقتی Sandbox روی حالت danger-full-access تنظیم شد، این زمان به ۱۲۲ میلیثانیه کاهش یافت؛ یعنی یک تفاوت ۱۲۸ برابری.
تأیید نهایی با اصلاح دستی بایتها (Byte-patching) در رشته لیتراسی فایلهای codex.exe و codex-command-runner.exe صورت گرفت. بدون هیچ تغییر دیگری، زمان spawn_ready از ۲۳.۴ ثانیه به ۰.۶ ثانیه و در اجراهای متوالی به ۰.۵ و ۰.۴۷ ثانیه کاهش یافت.
تشخیص توقفهای مشابه
این مورد یک نقشه راه برای تشخیص هر ابزاری است که قبل از اجرا چند ثانیه مکث میکند. گردش کار توصیه شده شامل استفاده از Procmon (Process Monitor) با دسترسی Administrator است:
۱. ضبط (Capture): ضبط را متوقف کنید (Ctrl+E)، پاک کنید (Ctrl+X) و درست قبل از بازتولید توقف، ضبط را شروع کنید.
۲. فیلتر (Filter): با Ctrl+L، مقدار Process Name را روی ابزار خود و Operation را روی CreateFile تنظیم کنید.
۳. تحلیل (Analyze): به Options $\rightarrow$ Select Columns بروید و ستونهای Duration و Result را اضافه کنید. سپس بر اساس Duration به صورت نزولی مرتب کنید.
۴. بررسی استک (Inspect Stack): روی طولانیترین ردیف راستکلیک کرده $\rightarrow$ Properties $\rightarrow$ Stack را انتخاب کنید.
اگر FLTMGR.SYS ظاهر شد، شما با یک درایور فیلتر سیستمفایل طرف هستید. برای شناسایی فیلتر خاص، از WPR (Windows Performance Recorder) برای ضبط و از WPA (Windows Performance Analyzer) برای خواندن بخش "Mini-Filter Delays" استفاده کنید و PID و TID را با دادههای Procmon تطبیق دهید. اگر استک از طریق تامینکننده شبکه رفته است، پردازش System را برای مسیرهای حاوی LanmanWorkstation فیلتر کنید تا فعالیتهای رجیستری و شبکه را مرتبط سازید.
تله توسعهدهنده
این باگ هشداری است درباره رشتههای «عیناً» (Verbatim) یا خام در زبانهایی مانند Rust، سیشارپ (@"...") و پاورشل (تک کوتیشن). توسعهدهندگان اغلب برای اطمینان، بکاسلشهای اضافی برای Escape کردن اضافه میکنند، اما در رشتههای خام، این بکاسلشهای اضافی به عنوان کاراکترهای واقعی پذیرفته میشوند. برای جلوگیری از تکرار چنین خطاهایی در محیط تولید، میتوان از سیستمهای Replay Harness برای تبدیل لاگهای گرانقیمت به تستهای رایگان استفاده کرد تا رفتارهای غیرمنتظره در محیطهای مختلف شناسایی شوند.
هنگام ساخت دستی مسیرهای ویندوز، قوانین سختگیرانه هستند:
- برای دستگاهها از
\\.\استفاده کنید. - از
\\?\فقط برای مسیرهای با طول گسترده استفاده کنید. - هرگز از
\\در ابتدا استفاده نکنید مگر اینکه واقعاً قصد دسترسی به یک سرور شبکه را داشته باشید. - از ارسال مسیرهای ساخته شده به
GetDriveTypeWاجتناب کنید، زیرا این تابع لایه تامینکننده را کوئری میکند و میتواند باعث مسدود شدن (Block) شود.
وضعیت فعلی و راهکارهای موقت
برای کسانی که در حال حاضر با توقف Codex دست و پنجه نرم میکنند، تنها راه حل فوری تنظیم sandbox = "danger-full-access" در بخش پیکربندی [windows] است. اگرچه این کار تأخیر را به حدود ۱۲۲ میلیثانیه کاهش میدهد، اما امنیت Sandbox را تضعیف میکند و یک راه حل دائمی نیست.
تا آخرین بررسی، این مورد در مخزن اصلی باز باقی مانده است. رشته بدشکل همچنان در شاخه main و در نسخه ۰.۱۵۵ آلفا وجود دارد. اصلاحیه از طریق بازرسی و Byte-patching تأیید شده است اما هنوز منتشر نشده است.
این حادثه ثابت میکند که در دنیای برنامهنویسی سیستمها، یک تک کاراکتر میتواند تفاوت بین یک ابزار سریع و یک تجربه خراب باشد. مشابه این اتفاقات کوچک اما ویرانگر را میتوان در تحلیلهای پسمرگ مربوط به حلقههای بینهایت در توکنهای هوش مصنوعی مشاهده کرد، جایی که یک خطای منطقی ساده منجر به هزینههای هنگفت میشود. قبل از نظریهپردازی، مسیر اجرا را ردیابی کنید؛ زیرا یک ردیف در Procmon که بر اساس مدت زمان مرتب شده باشد، ارزشمندتر از یک ساعت حدس زدن است.
گام بعدی شما
- اگر از ابزارهای CLI در ویندوز استفاده میکنید و با تأخیرهای نامعلوم مواجه هستید، از Procmon برای ردیابی توابع
CreateFileاستفاده کنید. - در کدنویسی Rust، هنگام تعریف مسیرهای سیستم، از صحت رشتههای خام (Raw Strings) اطمینان حاصل کنید.
- برای کاربران Codex، تنظیمات Sandbox را بررسی کنید تا از تأخیرهای احتمالی بکاهید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو