Libvips: ์งง์€ ์ด๋ฏธ์ง€ ๋˜๋Š” ushort ์ด๋ฏธ์ง€์˜ ๋Œ€๋žต์ ์ธ ์ปจ๋ณผ ๋ฃจ์…˜ ๋™์•ˆ Python ๋˜๋Š” libvips์˜ segfault

์— ๋งŒ๋“  2018๋…„ 11์›” 10์ผ  ยท  4์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: libvips/libvips

์•ˆ๋…• ์กด,

๋‚˜๋Š” # 1160์—์„œ ์–ธ๊ธ‰ ํ•œ ๋Œ€๋žต์ ์ธ ์ปจ๋ณผ ๋ฃจ์…˜์œผ๋กœ ์‹คํ—˜ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ์ง€์†์ ์ธ segfault๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์ง€๋งŒ ushort ์ด๋ฏธ์ง€๋ฅผ ์ปจ๋ณผ ๋ฃจ์…˜ ํ•  ๋•Œ๋งŒ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ python ๋˜๋Š” libvips์—์„œ segfault๊ฐ€ ๋ฐœ์ƒํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด๊ฒƒ์ด ์ด์ค‘ ๋ฌด๋ฃŒ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์œ„์น˜๋ฅผ ํ™•์ธํ•˜๊ธฐ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์‹คํ—˜์ด ํฌํ•จ ๋œ ํ…Œ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ๊ทธ ์•„๋ž˜๋Š” libvips.so.42.9.0 ๋‚ด๋ถ€์˜ segfault ์œ„์น˜์— ๋Œ€ํ•œ ์Šคํƒ ์ถ”์ ์ž…๋‹ˆ๋‹ค (ํ˜„์žฌ ๋””๋ฒ„๊น… ๋นŒ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๋„์›€์ด๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ).

python Python 2.7.15 :: Anaconda custom (64-bit) ์—์„œ pyvips ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ vips vips-8.7.0-Sun Jan 28 17:23:05 UTC 2018 ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.

๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ฐธ๊ณ  : ์‹ค์ œ๋กœ .py ํŒŒ์ผ :
segfault.txt

# /usr/bin/env python
import pyvips

slab = pyvips.Image.new_from_array([[1]*10]*10, scale=100)  # 10x10 moving average

n = 30000 # also segfaults when n=30000.  See note below.

# The following are all fine
uchar_im = pyvips.Image.black(n, n).cast('uchar')  # just to be sure it's uchar
uchar_im.conv(slab, precision='approximate', layers=1).write_to_file('uchar_conv.v')

float_im = pyvips.Image.black(n, n).cast('float')
float_im.conv(slab, precision='approximate', layers=1).write_to_file('float_conv.v')


# EVERY CONVOLUTION BELOW THIS LINE SEGFAULTS

# if n=1, completes by writing result to file, then segfaults in python:
# *** Error in `python': free(): invalid pointer: 0x00005651d79154c0 ***

# if n=30000, does not complete and segfaults in libvips
# [1049087.739802] worker[599]: segfault at 7f4cd631a000 ip 00007f4ce7f93318 sp 00007f4cd2caea70 error 4 in libvips.so.42.9.0[7f4ce7eb6000+1f5000]

ushort_im = pyvips.Image.black(n, n).cast('ushort')
ushort_im.conv(slab.cast('ushort'), precision='approximate', layers=1).write_to_file('ushort_conv.v')  # segfault happens here

ushort_im = pyvips.Image.black(n, n).cast('ushort')
ushort_im.conv(slab, precision='approximate', layers=1).write_to_file('ushort_conv.v')  # segfault would also happen here

short_im = pyvips.Image.black(n, n).cast('short')
short_im.conv(slab, precision='approximate', layers=1).write_to_file('short_conv.v')  # segfault would also happen here

n = 30000 ์ผ ๋•Œ ๊ด€๋ จ ์Šคํƒ ์ถ”์  ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Thread 52 "worker" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe64d5700 (LWP 4069)]
0x00007ffff4ab4c7d in ?? () from /usr/lib/libvips.so.42
(gdb) up
#1  0x00007ffff4b4e411 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#2  0x00007ffff4b4f0c9 in vips_region_fill () from /usr/lib/libvips.so.42
(gdb) up
#3  0x00007ffff4b50d53 in vips_region_prepare () from /usr/lib/libvips.so.42
(gdb) up
#4  0x00007ffff4ab65b3 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#5  0x00007ffff4b4e411 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#6  0x00007ffff4b4f0c9 in vips_region_fill () from /usr/lib/libvips.so.42
(gdb) up
#7  0x00007ffff4b50d53 in vips_region_prepare () from /usr/lib/libvips.so.42
(gdb) up
#8  0x00007ffff4b40d59 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#9  0x00007ffff4b4e411 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#10 0x00007ffff4b4f0c9 in vips_region_fill () from /usr/lib/libvips.so.42
(gdb) up
#11 0x00007ffff4b50d53 in vips_region_prepare () from /usr/lib/libvips.so.42
(gdb) up
#12 0x00007ffff4b40d59 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#13 0x00007ffff4b4e411 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#14 0x00007ffff4b4f0c9 in vips_region_fill () from /usr/lib/libvips.so.42
(gdb) up
#15 0x00007ffff4b50d53 in vips_region_prepare () from /usr/lib/libvips.so.42
(gdb) up
#16 0x00007ffff4b40d59 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#17 0x00007ffff4b4e411 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#18 0x00007ffff4b4f615 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#19 0x00007ffff4b50f5f in vips_region_prepare_to () from /usr/lib/libvips.so.42
(gdb) up
#20 0x00007ffff4b48228 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#21 0x00007ffff4b5171b in ?? () from /usr/lib/libvips.so.42
(gdb) up
#22 0x00007ffff4b51504 in ?? () from /usr/lib/libvips.so.42
(gdb) up
#23 0x00007ffff44e0a8a in g_thread_proxy (data=0x5555559df720) from /opt/anaconda/lib/libglib-2.0.so.0
(gdb) up
#24 0x00007ffff77e36ba in start_thread (arg=0x7fffe64d5700) at pthread_create.c:333
333 pthread_create.c: No such file or directory.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด๊ฒƒ์€ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๋ฒ„๊ทธ์ด๋ฏ€๋กœ์ด ๋ฒ„๊ทธ๋Š” ์—ด๋ ค ์žˆ์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  4 ๋Œ“๊ธ€

์œ„์˜ segfault.txt ๋งํฌ๋Š” github์—์„œ .py ํŒŒ์ผ ์ฒจ๋ถ€๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ํ…Œ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์ด์žˆ๋Š” .py ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

์˜ˆ, conva ์€ (๋Š”) ์‹ค์ œ๋กœ ์ œ์ž‘ ํ’ˆ์งˆ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ์›์˜ˆ ๐ŸŒฑ๐ŸŒฟ ๐ŸŒท ๋ฌธ์ œ๋ฅผํ•˜๊ณ  ์žˆ์œผ๋ฉฐ์ด ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฝค ์˜ค๋ž˜ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์—ฌ์ „ํžˆ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ๋ฌป๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ผ๋ถ€ ์˜ค๋ž˜๋œ ๋ฌธ์ œ๋ฅผ ๋‹ซ์Œ์œผ๋กœ์จ ์—ด๋ฆฐ ๋ฌธ์ œ ๋ชฉ๋ก์„๋ณด๋‹ค ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์šด ์„ธํŠธ๋กœ ์ค„์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๋ฒ„๊ทธ์ด๋ฏ€๋กœ์ด ๋ฒ„๊ทธ๋Š” ์—ด๋ ค ์žˆ์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰