Баг RTL: файл открытый первым не закрывается под голым Wine

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Re: Странный глюк Wine при перезаписи файла

Сообщение Cheb » 29.12.2014 17:31:28

:evil: Все баги давно отловлены, всё работает как часы, и даже страшную ЕРЕСЬ c FreeLibrary() закомментировал:
Код: Выделить всё
    if Detected then WineVersionString:= 'Wine' else Exit;
    Try
      ntdll:= LoadLibrary('ntdll.dll');
      if ntdll > 0 then begin
        vWineGetVersion := GetProcAddress(ntdll, 'wine_get_version');
        if Assigned(vWineGetVersion)
          then WineVersionString+= ' ' + vWineGetVersion();
        //FreeLibrary(ntdll);
      end;
    Except
    End;

Как лбом об стенку.
Причём, только при запуске коммандой wine <путь>chentrah.exe ! :evil:
При запуске из любого файлового менеджера - дабл коммандер (родной), тотал коммандер, гном коммандер (родной), даже из >wine explorer.exe - всегда, гарантированно, работает! :evil:

Изображение

:evil: :evil: :evil: :evil:

Добавлено спустя 5 часов 27 минут 20 секунд:
Я НАШОЛ! НАШОЛ, БЛДЖАД! ЭТО БАГ В RTL ПАСКАЛЯ!!!
:D :lol: :lol: :lol: :twisted: :twisted: :twisted: :evil: :evil: :evil: :evil: :!:

У меня в начале несколько раз с одним файлом елозит: открыть файл, закрыть файл, открыть файл, закрыть файл (проверяет можно ли записывать, тупо открывая на запись). Но! Эта С-с-с-сука его не закрывает! :evil:

Дано:
c:FPC2.6.4sourcertlobjpasclassesstreams.inc
Код: Выделить всё
destructor TFileStream.Destroy;

begin
  FileClose(FHandle);
end;


, что выливается в
c:FPC2.6.4sourcertlwinsysutils.pp
Код: Выделить всё
Procedure FileClose (Handle : THandle);
begin
  if Handle<=4 then
   exit;
  CloseHandle(Handle);
end;


В виндозе - всё пучком, хэндл = 28. Но когда это - первый файл, открытый под голым вайном, то этот драный в попу Handle равен точнёхонько 4 ! :evil: :evil: :evil: :evil: :evil:

И естессно ТОЛЬКО когда запускаешь коммандной строкой из терминала :x

Кто-нить, запостите пожалста на багтрекер, а то я себе не доверяю. Полезу туда сам - могу клавиатуру об монитор раз?##@% :evil:

У себя пока применю хак: при старте программы буду открывать мусорные файлы пока хэндл не станет больше 4.

Добавлено спустя 34 минуты 3 секунды:
Re: Баг RTL: файл открытый первым не закрывается под голым Wine
P.S. А вот ХРЕН. Просто открываю файлы-затычки - хендл оказывается 116, 120, 124, 128, 132.
Открываю файл который надо потом закрыть - хендл 4.

Таки баг вайна.
Последний раз редактировалось Cheb 11.11.2019 15:22:20, всего редактировалось 1 раз.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение Mirage » 29.12.2014 23:33:31

А зачем там это:
Код: Выделить всё
if Handle<=4 then
   exit;

Кто-нибудь знает?
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение скалогрыз » 30.12.2014 00:06:04

Mirage писал(а):А зачем там это:
Код: Выделить всё
if Handle<=4 then
   exit;

Кто-нибудь знает?

да, безымянные константы доставляяют.
Скорей всего был написан для спасения стандартных хендлов. Например: GetStdHandle(cardinal(STD_INPUT_HANDLE)) мне вернул 3 (winxp).
Но нигде в мсдн-е не гарантируется значения хендлов за исключением INVALID_HANDLE_VALUE.

код был таков изначально с первой ревизии SVN, так что возможно ответ есть в CVS версии фрипаскаля.
Ну и вообще имеет смысл либо баг-репорт сделать, либо на мейллисте спросить.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение Cheb » 30.12.2014 13:40:15

http://bugs.freepascal.org/view.php?id=27221 :(

Дойдут руки - заменю у себя в виндовс версии работу с файлами на собственный класс, юникодный и работающий на нативной для винды WideString.
TIniFile тоже придётся скопипастить, поскольку он так дебильно организован (поля private а не protected) что не поддаётся расширению, потомки не имеют доступа к ним.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение pda » 30.12.2014 16:01:16

скалогрыз писал(а):Но нигде в мсдн-е не гарантируется значения хендлов за исключением INVALID_HANDLE_VALUE.

Потому что это для Unix. Но там дефолтные потоки имеют диапазон 0..2. Т.е. в наличии:
1. Нет обёртки {$IFDEF UNIX}.
2. Слишком большой диапазон.
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение Sergei I. Gorelkin » 30.12.2014 16:22:16

Для unix используется совсем другой код (в файле rtl/unix/sysutils.pp), причем в нем никогда не было такого условия.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение pda » 30.12.2014 16:29:01

Забавно. Хотя в window 0..2 тоже предопределены для частичной совместимости с posix.
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение скалогрыз » 30.12.2014 17:08:15

pda писал(а):Забавно. Хотя в window 0..2 тоже предопределены для частичной совместимости с posix.

я бы рад согласится, но как я писал выше GetStdHandle(STD_INPUT_HANDLE) - вернул 3.
та же фунция с параметрами STD_ERROR_HANDLE, STD_OUTPUT_HANDLE возвращает 11 и 7 соответственно.

имхо, заглушка если и была добавленна, то только на основе каких-то тайных знаний какой-нить NT 3.0 или 9x - пережиток суеверий.
Но даже если и так, то код должен бы выглядеть так
Код: Выделить всё
const
  UNIX_COMPAT_HANDLE_VALUE = 4;
...

if Handle<=UNIX_COMPAT_HANDLE_VALUE then
   exit;


WDDD: такой заглушки в D7 нет.

2 Sergei I. Gorelkin - как можно до cvs-а добраться? :) логи почитать.

Добавлено спустя 16 минут 8 секунд:
Re: Баг RTL: файл открытый первым не закрывается под голым Wine
изучаем хендлы методом перебора :)
Код: Выделить всё
uses Windows, SysUtils;
var
  flags : LongWord;
  i : integer;
  err : LongWord;
begin
  flags :=0;
  for i:=0 to 20 do begin
    write(i,' ');
    if Windows.GetHandleInformation(THandle(i), flags) then
      write('is handle: ',IntToHex(flags, 8))
    else begin
      err:= GetLastError;
      if err = ERROR_INVALID_HANDLE then write('invalid handle')
      else write('error: ', err );
    end;
    writeln;
  end;
end.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение pda » 30.12.2014 17:33:55

скалогрыз писал(а):я бы рад согласится, но как я писал выше GetStdHandle(STD_INPUT_HANDLE) - вернул 3.

А тут надо внимательнее читать документацию:
The value of the handles returned by GetStdHandle are not 0, 1, and 2, so the standard predefined stream constants in Stdio.h (STDIN, STDOUT, and STDERR) cannot be used in functions that require a console handle.

Т.е. 0..2 - чисто файловые дескрипторы, для совместимости с posix, годящиеся только на fileread/filewrite, а GetStdHandle может вернуть другой дескриптор, который и на fileread/filewrite и на специальные консольные функции пригоден, вроде позиционирования курсора.
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение скалогрыз » 30.12.2014 18:05:59

The value of the handles returned by GetStdHandle are not 0, 1, and 2, so the standard predefined stream constants in Stdio.h (STDIN, STDOUT, and STDERR) cannot be used in functions that require a console handle.

это говорит о правилах использование хендла, т.к. CreateFile может сама вернуть значение от 0 и выше, что и происходит в случае Cheb-а.
Иными словами "не пологайтесь, на то, что хендлы стандартного вывода это 0, 1 и 2, и не пытайтесь использовать константы, а передавайте реально полученные хендлы из функци GetStdHandle()".

Это ладно. А вот значения 3 и 4 это константы чего? ведь код идёт как
if Handle<=4 then Exit

pda писал(а):Т.е. 0..2 - чисто файловые дескрипторы, для совместимости с posix, годящиеся только на fileread/filewrite, а GetStdHandle может вернуть другой дескриптор, который и на fileread/filewrite и на специальные консольные функции пригоден, вроде позиционирования курсора.

это всё хорошо, но паскаль никогда не отличался совместимостью с stdio.h
например, сий код это абсурд:
Код: Выделить всё
var
  t : string;
begin
  t:=length('test');
  FileWrite(0, t, length(t));
  FileWrite(1, t, length(t));
  FileWrite(2, t, length(t));
end.

:)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение pda » 30.12.2014 19:00:17

скалогрыз писал(а):т.к. CreateFile может сама вернуть значение от 0 и выше, что и происходит в случае Cheb-а.

Мы, кажется, не спорим о том есть баг в rtl или нет. Есть. :)

скалогрыз писал(а):Иными словами "не пологайтесь, на то, что хендлы стандартного вывода это 0, 1 и 2, и не пытайтесь использовать константы, а передавайте реально полученные хендлы из функци GetStdHandle()".

Ниееет. Для работы с windows-специфичными консольными функциями не используйте стандартные хендлы, а пользуйтесь GetStdHandle().

скалогрыз писал(а):это всё хорошо, но паскаль никогда не отличался совместимостью с stdio.h

Ну, приведённый код и правда абсурд (t : string; t:=length('test');), но речь не об этом, да fpc использует в windows GetStdHandle() для подключения к консоли. Соответственно, имеем стандартные переменные, типа StdOutputHandle, которая в linux стандартно равна 1, а в Windows у меня, например, 7.

Так что или сравнивать с ними или... Я вообще за то, чтобы убрать все проверки, кроме INVALID_HANDLE_VALUE, т.к. если человек собирается работать со стандартными потоками через TFileStream, то он должен знать что делает, при доступности:
Код: Выделить всё
InputStream := THandleStream.Create(GetStdHandle(STD_INPUT_HANDLE));
OutputStream := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE));


Добавлено спустя 11 минут 59 секунд:
Re: Баг RTL: файл открытый первым не закрывается под голым Wine
скалогрыз писал(а):А вот значения 3 и 4 это константы чего?

Полагаю, это двойная ошибка. Изначально хотели защитить стандартные потоки, но забыли, что они начинаются с нуля. Потом хотели написать <4, но ошиблись.
Другая версия - проверили результат GetStdHandle() и решили, что надо защищать 0..4 (хотя логичнее было бы 0..5).
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение скалогрыз » 30.12.2014 19:12:28

pda писал(а):
скалогрыз писал(а):т.к. CreateFile может сама вернуть значение от 0 и выше, что и происходит в случае Cheb-а.

Мы, кажется, не спорим о том есть баг в rtl или нет. Есть. :)

меня больше всего интересует почему 4.
я бы ещё согласился со стандартными хендлами, в том случае если проверка была бы Handle<3 или Handle<=2 ... но 4!
это как половинка от 42? :mrgreen:
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение SSerge » 31.12.2014 04:17:39

Файловый дескриптор 4 - принтер stdprn (PRN)
Файловый дескриптор 5 - stdaux (СOM1)

наследие MS-DOS
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение скалогрыз » 31.12.2014 07:41:58

SSerge писал(а):Файловый дескриптор 4 - принтер stdprn (PRN)
Файловый дескриптор 5 - stdaux (СOM1)

наследие MS-DOS

допустим... тогда дескриптор 3 это что? :)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Баг RTL: файл открытый первым не закрывается под голым W

Сообщение SSerge » 31.12.2014 08:51:18

А.И.Касаткин "Управление ресурсами" (С) Минск, 1992

Для каждой программы MS-DOS создает свою уникальную таблицу открытых файлов, но массив описаний используется только один. Сама таблица открытых файлов первоначально хранится в специальной области памяти - Program Segment Prefix (PSP), В PSP под таблицу открытых файлов используется 80 байт, начиная со смещения 0018h. Следовательно, по умолчанию программа имеет не более 20 префиксов. Учитывая, что первые пять перфиксов зарезервированы под префиксы стандартных файлов [дальше несущественно]


Оттуда же далее:
0x0000 - CON stdin, стандартное устройство ввода
0x0001 - CON stdout - стандартное устройство вывода
0x0002 - CON stderr - стандартное устройство выдачи ошибок. Обычно дублирует префикс 1
0x0003 - AUX stdaux - стандартное дополнительное устройство. По умолчанию соответствует COM1
0x0004 - PRN stdprn - стандартное устройство печати


страница 53 :)

В предыдущем высказывании насчет пятого дескриптора была Википедия. В википедии лажа. :D Этот же источник достоверен.

Так что, коллеги, лажает скорее Wine, чем RTL - не должно бы ей под пользовательские файлы отдавать дескрипторы ниже пятого.
Ибо "стандартный принтер" с дескриптором 4 во всех виндовс до миллениума влючительно был гарантированно и печатал в обход драйвера на порт LPT, начиная с XP этот поток вроде как перехватывался драйвером и направлялся как plain text на принтер по умолчанию
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru