Bug 1689

Summary: При печати документов 1c77 падает
Product: WINE@Etersoft Reporter: Глеб Кордюков <sonner>
Component: Печать ; Диалог печатиAssignee: Виталий Перов <vitperov>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P5 CC: 1c, baraka, lav, shade
Version: 1.0.9   
Target Milestone: ---   
Hardware: PC   
OS: SUSE   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on: 1363, 1911    
Bug Blocks: 443, 777, 7389    
Attachments: Install.log
wine.log

Description Глеб Кордюков 2008-04-12 15:07:11 MSD
Created attachment 394 [details]
Install.log

При массовой печати документов "Реализация" через "Групповую
обработку документов" 1С вылетает, НО если, после загрузки 1С открыть
печатную форму "Реализации", посмотреть, закрыть, и попытаться провести
массовую печать через "Групповую обработку документов", все начинает
работать нормально. Этот баг висит уже давно и сильно мешает нам
работать! - плохо.

Для решения данной проблемы направляю Вам демо-конфигурацию - DataBase с
нашими настройками: ftp://ftp.referent.ru/Citrix/Arhiv.tar.gz
Используются и прилагаются доп. компоненты, зарегите 1CPP.dll и FormEx.dll

Пользователь Администратор, пароля нет. В ЖД лежит ряд реализаций и
документ "Ведомость выдачи документов клиенту". Откройте документ
Ведомость, нажмите кнопку "Печать Документов", выберите любой принтер и
нажмите кнопку "Выполнить" - 1С вылетает.
Comment 1 Глеб Кордюков 2008-04-12 15:07:45 MSD
Created attachment 395 [details]
wine.log
Comment 2 Денис Баранов 2008-05-31 19:19:41 MSD
*** Bug 1363 has been marked as a duplicate of this bug. ***
Comment 3 Денис Баранов 2008-05-31 19:21:42 MSD
Ошибка воспроизвелась. При нажатии на выполнить, вылетает в дебаг:

err:syslevel:_EnterSysLevel (0x7eee0e60, level 2): Holding 0x7edc4ba0, level 3. Expect deadlock!
err:syslevel:_EnterSysLevel (0x7eee0e60, level 2): Holding 0x7edc4ba0, level 3. Expect deadlock!
err:syslevel:_EnterSysLevel (0x7eee0e60, level 2): Holding 0x7edc4ba0, level 3. Expect deadlock!
err:syslevel:_CheckNotSysLevel Holding lock 0x7edc4ba0 level 3
wine: Unhandled exception 0x80000003 at address 0x7b88cdf0 (thread 0009), starting debugger...
WineDbg starting on pid 0008
0x7b88cdf0 _CheckNotSysLevel+0x40 in kernel32: int      $3
Wine-dbg>bt
Backtrace:
=>1 0x7b88cdf0 _CheckNotSysLevel+0x40() in kernel32 (0x00325804)
  2 0x7ed93a30 in gdi32 (+0x43a30) (0x00325814)
  3 0x7ed6c512 DeleteDC+0x22() in gdi32 (0x00325844)
  4 0x5f4038c2 in mfc42 (+0x38c2) (0x00325864)
  5 0x7800c9b8 in msvcrt (+0xc9b8) (0x00327840)
  6 0x5f4023d8 in mfc42 (+0x23d8) (0x00327850)
  7 0x5f4022ae in mfc42 (+0x22ae) (0x00327880)
  8 0x5f402c25 in mfc42 (+0x2c25) (0x003278b0)
  9 0x2502540e in moxel (+0x2540e) (0x00327908)
  10 0x5f402976 in mfc42 (+0x2976) (0x00327958)
  11 0x5f4029d7 in mfc42 (+0x29d7) (0x003279f0)
  12 0x5f401cea in mfc42 (+0x1cea) (0x00327a10)
  13 0x5f401c73 in mfc42 (+0x1c73) (0x00327a70)
  14 0x5f401bfb in mfc42 (+0x1bfb) (0x00327a8c)
  15 0x5f401bba in mfc42 (+0x1bba) (0x00327ab8)
  16 0x7ee9c36a WINPROC_wrapper+0x1a() in user32 (0x00327ae8)
  17 0x7ee9ca6e WINPROC_wrapper+0x71e() in user32 (0x00327b28)
  18 0x7eea2081 in user32 (+0xb2081) (0x00327b68)
  19 0x7ee647fa in user32 (+0x747fa) (0x00327bd8)
  20 0x7ee67a02 in user32 (+0x77a02) (0x00327c38)
  21 0x7ee67e1e SendMessageA+0x4e() in user32 (0x00327c78)
  22 0x2a055cc5 in basic (+0x55cc5) (0x00000001)
  23 0x00000000 (0x00000000)
Comment 4 Денис Баранов 2008-05-31 19:26:56 MSD
Бутылка: 1c77-27, информационная база №1.
Comment 5 Виталий Перов 2008-06-03 21:09:22 MSD
при вызове из BITMAP_SelectObject функции BITMAP_SetOwnerDC, выполняется создание нового bitmap, при этом:
bitmap->funcs = dc->funcs
если после этого посмотреть bitmap->funcs->pGetBitmapBits , то оно равно нулю.

а падение происходит при вызове из PSDRV_Brush функции GetBitmapBits.
В ней выполняется:
    if(bmp->funcs && bmp->funcs->pGetBitmapBits)
    {
        TRACE("Calling device specific BitmapBits\n");
        ret = bmp->funcs->pGetBitmapBits(hbitmap, bits, count);
    }
указатель pGetBitmapBits должен быть равен нулю, а на момент выполнение туда попадает случайное значение
Comment 6 Виталий Перов 2008-06-03 22:30:43 MSD
При предварительном просмотре всё нормально печатается, при этом функция PSDRV_Brush не вызывается.
Comment 7 Виталий Перов 2008-06-03 23:09:19 MSD
функция PSDRV_Brush падает при вызове PSDRV_WritePatternDict.
При отключении PSDRV_WritePatternDict PSDRV_Brush завершается успешно, вызывающая её PSDRV_PatBlt тоже завершается успешно,а падает значительно выше.
Comment 8 Виталий Перов 2008-06-05 13:32:02 MSD
При добавлении строк, служащих только для вывода информации стало падать даже после предварительноко просмотра. Падает на функции PSDRV_WritePatternDict().
Comment 9 Виталий Перов 2008-06-05 14:28:12 MSD
изначально в функцию предаются очень странные значения bitmap:
bmWidth=2112886257 bmHeight=10, bmBitsPixel=50 bmPlanes=28196, bmWidthBytes=3305028

Хоть данная функция и содержит потенциальные ошибки, но дело не в ней.
Ещё до её вызова в область стека, где хранится bitmap попадают случайные значения
Comment 10 Виталий Перов 2008-06-06 14:06:08 MSD
Падает потому, что в функции _CheckNotSysLevel
стоит вызов DbgBreakPoint(), которая определена как:

void WINAPI DbgBreakPoint(void)
{
     kill(getpid(), SIGTRAP);
}

если в этом месте не вызывать DbgBreakPoint(), то при печати 1с не падает, но в консоль постоянно(даже после печати) поступают сообщения:
err:syslevel:_EnterSysLevel (0x7edab160, level 2): Holding 0x7ec80640, level 3. Expect deadlock!

Отулючать данную проверку нельзя, надо разобраться почему в этом месте она не проходит.
Не проходит она при вызове из функции DeleteDC()

Comment 11 Виталий Перов 2008-06-06 15:50:53 MSD
При вызове _EnterSysLevel() происходит блокировка критической секции.
Если не был вызван _LeaveSysLevel, то при вызове _CheckNotSysLevel процесс принудительно завершается

Подозрительно в этом плане выглядит функция GDI_GetObjPtr.
Вначале выполняется  _EnterSysLevel( &GDI_level );
, а _LeaveSysLevel выполняется только в случае неправильного хендла
if (!ptr)
    {
        _LeaveSysLevel( &GDI_level );
        WARN( "Invalid handle %p\n", handle );
    }
Comment 12 Vitaly Lipatov 2008-06-06 17:21:33 MSD
Потому что Leave выполняется из GDI_ReleaseObj
который обязан вызвать каждый.
Скорее всего дело в непарности GDI_GetObjPtr/GDI_ReleaseObj
в каком-то месте.
Comment 13 Виталий Перов 2008-06-06 18:29:50 MSD
Падение происходит потому, что в функции GetBitmapBits программа не доходит до GDI_ReleaseObj.
А происходит это потому, что вызывается:     
if(bmp->funcs && bmp->funcs->pGetBitmapBits)
    {
        TRACE("Calling device specific BitmapBits\n");
        ret = bmp->funcs->pGetBitmapBits(hbitmap, bits, count);
    }

на первых страницах pGetBitmapBits=NULL. Потот туда каким-то образом попадает случайное число, программа переходит по данному адресу, и падает.

т.е если pGetBitmapBits остаётся равным NULL, то всё работает.

НО: При предварительном просмотре pGetBitmapBits не равен NULL.
указатель имеет вполне определённое постоянное значение:
bm->funcs->pGetBitmapBits=0x7e7ae495 
Comment 14 Виталий Перов 2008-06-06 18:50:06 MSD
при повторном запуске адрес этот изменяется, но принадлежит он функции X11DRV_GetBitmapBits.
Т.е если был включен предварительный просмотр, то при печати используется функция копирования от графического драйвера
Comment 15 Виталий Перов 2008-06-06 23:03:18 MSD
Память перезаписывает функция внутри oleaut32.dll
ConnectionPointImpl_Construct+0x8d [/srv/vitperov/Projects/wine/dlls/oleaut32/connpt.c:114]

Возможно память до этого случайно освобождается, а данная функция просто пишет поверх освободившегося куска памяти.
Comment 16 Виталий Перов 2008-06-07 17:54:57 MSD
функция BITMAP_SetOwnerDC ставит функции обработки для данного bitmap.

в случае если bitmap->funcs == 0 она берёт из из DC:
bitmap->funcs = dc->funcs;

Но, если там уже что-то есть, то новые функции функции обработки остаются старыми.
Если там каким-то чудом оказывается на месте pGetBitmapBits записан 0, то печать работает нормально. если же там другое значение, то программа переходит по этому адресу и вылетает.

Думаю если в данном месте принудительно обновлять функции, то проблема исчезнет.
Но всё-же нужно узнать откуда в bitmap->funcs появляются такие значения
Comment 17 Vitaly Lipatov 2008-06-07 18:13:25 MSD
В общем делаем такой хак, некогда больше заниматься.
Планируем проверить поведение SetOwnerDC в винде в случае уже имеющегося funcs, ну и конечно стоит попытаться выяснить что же там происходит, чей это адрес.
Comment 18 Виталий Перов 2008-06-07 18:49:48 MSD
пытался выяснить куда указывает старый адрес funcs.
смотрел отдельные функции в funcs - там просто случайные числа (по указанным адресам перехода просто попадаем в середину какой-то функции).
Cкорее всего это освобождённая память т.к значения там остаются постоянные, и изменяются только перед падением 

В последнее время бага отказывается воспроизводится (падает 1 раз из 20) даже при откате всех внесённых изменений.
Странно то, что в funcs в переменной pGetBitmapBits всегда 0, поэтому всё работает. Притом соседние функции не нулевые.

Т.к в последнее время почти невозмножно заставить программу падать, то предлагаю сделать предложенное изменение и протестировать результат. Если бага всё же появится, то разбираться дальше
Comment 19 Виталий Перов 2008-06-19 19:37:34 MSD
патч уже вошёл в новую сборку. Сейчас всё должно работать