Надо разобраться, если возможно отличить, что открытие файла не удалось из-за превышения лимита на количество дескрипторов, то нужно выводить специальное сообщение.
В случае возникновения ошибки открытия сравнивать количество открытых дескрипторов с максимальным?
Для начала надо проанализировать код ошибки.
#include <stdio.h> #include <errno.h> #define N 10000 #define name "a.txt" #define attr "r" main(){ unsigned int i; FILE *f[N]; for(i = 0; i < N; i++){ f[i] = fopen(name, attr); if(f[i] == NULL){ printf("Invalid f[%u] = NULL: code = %i\n", i, errno); } else { printf("Normal f[%u] = %x\n", i, f); } } for(i = 0; i < N; i++){ fclose(f[i]); } return 0; } срабатывает при невозможности открыти файл так: ... Normal f[1014] = bff2f7ec Normal f[1015] = bff2f7ec Normal f[1016] = bff2f7ec Normal f[1017] = bff2f7ec Normal f[1018] = bff2f7ec Normal f[1019] = bff2f7ec Invalid f[1020] = NULL: code = 24 Invalid f[1021] = NULL: code = 24 Invalid f[1022] = NULL: code = 24 Invalid f[1023] = NULL: code = 24 Invalid f[1024] = NULL: code = 24 Invalid f[1025] = NULL: code = 24 ... #define EMFILE 24 /* Too many open files */ // из errno.h
- printf("Normal f[%u] = %x\n", i, f); + printf("Normal f[%u] = %x\n", i, f[i]); конено же :)
А дальше нужно разобраться, какой код ошибки будет в Wine для CreateFile, и в каком месте вставить проверку. А главное, ведь надо ещё суметь программу с сообщением об ошибке запустить - то есть предварительно закрыть некоторые файлы. Сложности есть, пока откладываю.
по идее должно возникнуть: ERROR_TOO_MANY_OPEN_FILES 4 0x4 ( http://msdn.microsoft.com/en-us/library/ms681382(VS.85).aspx ) сейчас я проверяю действительно ли это работает у нас.
> сейчас я проверяю действительно ли это > работает у нас. > всё работает: ... Normal f[9914] = 9b10 Normal f[9915] = 9b14 Normal f[9916] = 9b18 Normal f[9917] = 9b1c Normal f[9918] = 9b20 Normal f[9919] = 9b24 Normal f[9920] = 9b28 Normal f[9921] = 9b2c Normal f[9922] = 9b30 Normal f[9923] = 9b34 Invalid f[9924] = INVALID_HANDLE_VALUE: errno = 2, GetLastError = 4 Invalid f[9925] = INVALID_HANDLE_VALUE: errno = 2, GetLastError = 4 Invalid f[9926] = INVALID_HANDLE_VALUE: errno = 2, GetLastError = 4 Invalid f[9927] = INVALID_HANDLE_VALUE: errno = 2, GetLastError = 4 Invalid f[9928] = INVALID_HANDLE_VALUE: errno = 2, GetLastError = 4 ...
код: #include <windows.h> #include <stdio.h> #include <errno.h> #define N 10000 main(){ unsigned int i, handle_edge = N; HANDLE f[N]; const char name[] = "a.txt"; for(i = 0; i < N; i++){ f[i] = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if(f[i] == INVALID_HANDLE_VALUE){ DWORD err = GetLastError(); if(handle_edge == N) handle_edge = i + 1; printf( "Invalid f[%u] = INVALID_HANDLE_VALUE: " "errno = %i, GetLastError = %x\n", i, errno, err ); } else printf("Normal f[%u] = %x\n", i, f[i]); } for(i = 0; i < handle_edge; i++) if(!CloseHandle(f[i])) printf("Invalid close handle f[%u]\n", i); return 0; }
Программа по баге 4260 практически дописана, можно браться за её вызов в нужном месте.
Реализовал вывод сообщений с помощью eterx11msg. Одновременно выводится не более одного сообщения. Кроме сообщения о превышении лимита на количество дескрипторов для процесса, должны выводиться сообщения о запуске нескольких копий wineserver при отсутствии терминальной лицензии, об использовании неподходящего модуля ядра для cifs, о превышении числа одновременно работающих с файлом процессов.
Вывод сообщения о запуске второго wineserver надо было вставить в сам wineserver, так как он в этом случае завершается и до обращения к etersoft_sharing_open дело не доходит. Патч: server: Show error message if a license do not allow to run second wineserver (eterbug #2761).
WINE@Etersoft 1.0.11 eter8.5\eter5 Вывод предупреждения при не терминальной лицензии работает.
-