libc: квирки DSS — возврат WRITE и лимит манипуляторов; тесты fdmax/fbench
- ESTEX WRITE ($14) на успехе возвращает DE=0, а НЕ счётчик записанного (вопреки докам; solid-c в своём fflush тоже отключил сравнение по счётчику) — write() теперь судит по CF/A: CF=0&A=0 → n, CF=0&A!=0 → ENOSPC/-1 - DSS выдаёт 8 манипуляторов (fd 2..9; fd 1 держит шелл под запущенный exe), а 9-й OPEN не возвращает 06h — ВЕШАЕТ систему; предохранитель _fd_guard: счётчик в open()/close(), отказ EMFILE без захода в DSS - tests/fdmax — эмпирика лимита (8 хендлов, затем EMFILE=6); tests/fbench — бенчмарк буферизации (floor 512-байтными read, оценка небуферизованного по 1-байтным, fgetc/fgets/fputc) - filetest расширен: raw-probe возврата write, сценарий r+ (чтение-запись-чтение с инвалидацией буфера), ungetc, fprintf Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# Build fdmax.exe — проверка лимита открытых файлов DSS/FILE-таблицы.
|
||||
# TEST.TXT нужен тесту как открываемый файл — кладём на дискету
|
||||
# и при одиночном `make run` (берём из tests/cat).
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := fdmax
|
||||
EXTRA_DATA := ../cat/test.txt
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* fdmax — эмпирическая проверка лимита одновременно открытых файлов.
|
||||
*
|
||||
* ФАКТ (прогон 2026-07-06, DSS 1.71.57): DSS выдал 8 манипуляторов
|
||||
* (fd 2..9; fd 1 держит шелл DSS под запущенный .exe), а 9-й OPEN
|
||||
* НЕ вернул ошибку — ПОВЕСИЛ систему. После этого в libc/io/open.c
|
||||
* добавлен предохранитель _fd_guard (отказ EMFILE на 9-м open без
|
||||
* захода в DSS), и этот тест снова безопасен.
|
||||
*
|
||||
* 1) Низкий уровень: open("TEST.TXT") в цикле — ожидание: 8 хендлов,
|
||||
* затем EMFILE=6 от предохранителя libc (не от DSS!).
|
||||
* 2) Высокий уровень: fopen до NULL — таблица OPEN_MAX (8), EMFILE.
|
||||
*
|
||||
* Требует TEST.TXT на диске (без него обе фазы дадут ENOENT=3).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRY_MAX 32
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fds[TRY_MAX];
|
||||
int n = 0;
|
||||
|
||||
/* ----- 1. Голые манипуляторы DSS ----- */
|
||||
errno = 0;
|
||||
while (n < TRY_MAX) {
|
||||
int fd = open("TEST.TXT", O_RDONLY);
|
||||
if (fd < 0) break;
|
||||
fds[n++] = fd;
|
||||
printf("open #%d -> fd=%d\n", n, fd);
|
||||
}
|
||||
printf("low-level: %d handles, then errno=%d (%s)\n",
|
||||
n, errno, strerror(errno));
|
||||
for (int i = 0; i < n; i++) close(fds[i]);
|
||||
|
||||
/* ----- 2. fopen / таблица FILE ----- */
|
||||
FILE *fps[TRY_MAX];
|
||||
int m = 0;
|
||||
errno = 0;
|
||||
while (m < TRY_MAX) {
|
||||
FILE *fp = fopen("TEST.TXT", "r");
|
||||
if (!fp) break;
|
||||
fps[m++] = fp;
|
||||
}
|
||||
printf("fopen: %d streams (OPEN_MAX=%d), then errno=%d (%s)\n",
|
||||
m, OPEN_MAX, errno, strerror(errno));
|
||||
for (int i = 0; i < m; i++) fclose(fps[i]);
|
||||
|
||||
puts("fdmax done.");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user