Summary: | 1С8.1: При закрытии вылетает в дамп | ||
---|---|---|---|
Product: | WINE@Etersoft | Reporter: | Денис Баранов <baraka> |
Component: | Общее | Assignee: | Александр Морозов <amorozov> |
Status: | CLOSED FIXED | QA Contact: | Денис Баранов <baraka> |
Severity: | minor | ||
Priority: | P4 | CC: | baraka, kondratyuk, lav, night, shpigor, sonner |
Version: | unspecified | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All | ||
Whiteboard: | |||
Заявки RT: | Связано с: | ||
Дата напоминания: | |||
Bug Depends on: | 6061 | ||
Bug Blocks: | 437, 5101 | ||
Attachments: | бектрейс |
Проявляется на WINE@Etersoft 1.0.11 eter11/eter6, на eter10 тоже. Воспроизвести можно в бутылке 1c81/1c81AccountingBase. При выборе базы надо выбрать "Торговля", после входа в базу выбираем Документы->Затраты->Авансовые отчеты, открываем авансовый отчёт, нажимаем кнопку "Авансовый отчет" внизу, нажимаем Ctrl-P, в появившемся окне OK, закрываем окно 1С. Падает в BITMAP_DeleteObject при вызове funcs->pDeleteBitmap. В pDeleteBitmap находится какой-то мусор. trace:bitmap:BITMAP_DeleteObject 0x3a4 trace:gdi:GDI_GetObjPtr (0x3a4): enter 1 trace:gdi:GDI_ReleaseObj (0x3a4): leave 1 trace:bitmap:BITMAP_DeleteObject funcs 0x3b51678 trace:bitmap:BITMAP_DeleteObject funcs->pDeleteBitmap 0x1 err:int:__wine_emulate_instruction instr=0x1 context=0x32f508 CS=0073 IP=0001 wine: Unhandled page fault on read access to 0x00000001 at address 0x1 (thread 0009), starting debugger... preloader: Warning: failed to reserve range 00000000-00010000 WineDbg starting on pid 0008 Unhandled exception: page fault on read access to 0x00000001 in 32-bit code (0x00000001). Register dump: CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b EIP:00000001 ESP:0032f82c EBP:0032f8d8 EFLAGS:00210202( - 00 - -RI1) EAX:000003a4 EBX:7eaffff4 ECX:00000000 EDX:00000001 ESI:7ea70000 EDI:01601300 Stack dump: 0x0032f82c: 7ea8d45d 000003a4 7eb07f70 7eae8703 0x0032f83c: 7eae86b1 00000001 7bcca3e5 00000000 0x0032f84c: 0032f8f0 7bcca388 00000046 00000046 0x0032f85c: 7bcc9f80 7bcaeff4 0000001f 0032f898 0x0032f86c: 7bc35b24 7eaf09b0 0032f8f0 7eb08121 0x0032f87c: 7eaf0bf5 00000000 7bcca244 0000005d Backtrace: =>0 0x00000001 (0x0032f8d8) 1 0x7eac471e DeleteObject+0x630(obj=0x3a4) [/home/amorozov/Projects/wine-eter-1.0.11/dlls/gdi32/gdiobj.c:837] in gdi32 (0x0032fa98) 2 0x7ea8e205 BRUSH_DeleteObject+0x9d(handle=0x3a8) [/home/amorozov/Projects/wine-eter-1.0.11/dlls/gdi32/brush.c:424] in gdi32 (0x0032fad8) 3 0x7eac471e DeleteObject+0x630(obj=0x3a8) [/home/amorozov/Projects/wine-eter-1.0.11/dlls/gdi32/gdiobj.c:837] in gdi32 (0x0032fc98) 0x00000001: -- no code accessible -- Последовательность действий 1С такая: BITMAP_SelectObject (0x6c, 0x2060) DC_InitDC (0x3b55f70) BRUSH_SelectObject (0x3a8, 0x2060) BITMAP_SetOwnerDC (0x3a4, 0x3b55f70) DeleteDC (0x2060) BITMAP_DeleteObject (0x3a4) - здесь происходит падение 0x3b55f70 - это указатель на DC, возвращаемый get_dc_ptr(0x2060) > Падает в BITMAP_DeleteObject при вызове funcs->pDeleteBitmap.
> В pDeleteBitmap находится какой-то мусор.
Область памяти, на которую указывает funcs, освобождается в функции DRIVER_release_driver, которую вызывает DeleteDC. Значение указателю funcs присваивается в функции BITMAP_SetOwnerDC, вызываемой до вызова DeleteDC.
(In reply to comment #3) > Последовательность действий 1С такая: > BITMAP_SelectObject (0x6c, 0x2060) > DC_InitDC (0x3b55f70) > BRUSH_SelectObject (0x3a8, 0x2060) > BITMAP_SetOwnerDC (0x3a4, 0x3b55f70) > DeleteDC (0x2060) > BITMAP_DeleteObject (0x3a4) - здесь происходит падение > 0x3b55f70 - это указатель на DC, возвращаемый > get_dc_ptr(0x2060) Нужно проверить, падает ли в Windows удаление несуществующего объекта. Также возможно нужно добавить обработчик падения и всё. > Нужно проверить, падает ли в Windows удаление > несуществующего объекта. Простой тест под WINE, делающий нечто подобное, не падает, хотя в нём и используется уже освобождённая память. Для того, чтобы он упал, надо, чтобы в этой памяти было записано что-то новое. Подобное поведение может быть и в Windows. То есть если не упадёт, это ещё не значит, что так можно делать. > Также возможно нужно добавить обработчик > падения и всё. Что за обработчик падения? (In reply to comment #6) > > Нужно проверить, падает ли в Windows удаление > > несуществующего объекта. > Простой тест под WINE, делающий нечто > подобное, не падает, хотя в нём и > используется уже освобождённая память. Для > того, чтобы он упал, надо, чтобы в этой > памяти было записано что-то новое. > Подобное поведение может быть и в Windows. То > есть если не упадёт, это ещё не значит, что > так можно делать. Что-то я не про то ответил. При удалении несуществующего объекта простая программа не упала ни в Windows, ни в WINE. Существуют функции DRIVER_get_driver и DRIVER_release_driver, которые увеличивают и уменьшают число ссылок на структуру graphics_driver, содержащую структуру funcs, из-за преждевременного освобождения которой падает 1С. Использовал эти функции в функциях BITMAP_*, но проблему это не решило. При этом в добавленных логах можно увидеть, например, такое: trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55 trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55 trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55 trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55 Хотя вроде бы такого быть не может, счётчик должен уменьшаться, если не вызывается DRIVER_get_driver. > trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55
> trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55
> trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55
> trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 55
Разобрался с чем это связано, счётчик увеличивался в функции load_display_driver, которая вызывается из DRIVER_load_driver:
trace:driver:load_display_driver driver 0x11b928 funcs 0x11b938 count 66 (thread 9)
trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 65 (thread 9)
trace:driver:load_display_driver driver 0x11b928 funcs 0x11b938 count 66 (thread 9)
trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 65 (thread 9)
trace:driver:load_display_driver driver 0x11b928 funcs 0x11b938 count 66 (thread 9)
trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 65 (thread 9)
trace:driver:load_display_driver driver 0x11b928 funcs 0x11b938 count 66 (thread 9)
trace:driver:DRIVER_release_driver driver 0x11b928 funcs 0x11b938 count 65 (thread 9)
> Существуют функции DRIVER_get_driver и DRIVER_release_driver,
> которые увеличивают и уменьшают число
> ссылок на структуру graphics_driver, содержащую
> структуру funcs, из-за преждевременного
> освобождения которой падает 1С.
> Использовал эти функции в функциях BITMAP_*, но
> проблему это не решило.
Разобрался, почему это не работало. Ссылка funcs может быть проинициализирована ещё и в CreateDIBSection, а не только в функциях BITMAP_*. Патч:
gdi32: Prevent freeing graphics_driver when it is used by bitmap object (eterbug #4394).
Принято. 1.0.12-eter1.2/1 В eterhack откатил коммит: commit c3cd0cfba9932e683fb6ddddb8fe63b2c0f01321 Author: Alexander Morozov <amorozov@etersoft.ru> gdi32: Prevent freeing graphics_driver when it is used by bitmap object (eterbug #4394). Т.к. при сломал сборку wine: bitmap.o: In function `BITMAP_SetOwnerDC': /srv/shpigor/Projects/WINE/wine-eterhack/dlls/gdi32/bitmap.c:588: undefined reference to `DRIVER_release_driver' /srv/shpigor/Projects/WINE/wine-eterhack/dlls/gdi32/bitmap.c:589: undefined reference to `DRIVER_get_driver' /srv/shpigor/Projects/WINE/wine-eterhack/dlls/gdi32/bitmap.c:579: undefined reference to `DRIVER_get_driver' bitmap.o: In function `BITMAP_DeleteObject': /srv/shpigor/Projects/WINE/wine-eterhack/dlls/gdi32/bitmap.c:675: undefined reference to `DRIVER_release_driver' dib.o: In function `CreateDIBSection': /srv/shpigor/Projects/WINE/wine-eterhack/dlls/gdi32/dib.c:1351: undefined reference to `DRIVER_get_driver' На текущем eterhack не воспроизводится Закрываю. |
Created attachment 1350 [details] бектрейс Если открыть 1С 8.1, зайти в документы> Авансовые отчеты>Распечатать любой отчет и сразу после этого закрыть 1С, то проходит запись дампа. В приложении бэктрейс.