I am having trouble with segmentation fault in Python. Sometimes it happens, sometimes it doesn't but when it does I used gdb python
as explained in this answer and I get this result:
[... a lot more lines before this ...]
[New Thread 0x7fff097fa700 (LWP 23244)]
Thread 31 "python" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fff4affd700 (LWP 23227)]
__GI___libc_free (mem=0x10035) at malloc.c:3103
3103 malloc.c: No such file or directory.
(gdb) backtrace
#0 __GI___libc_free (mem=0x10035) at malloc.c:3103
#1 0x00007fff70cc2a39 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#2 0x00007fff70939ef5 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#3 0x00007fff7103a6c5 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#4 0x00007fff70d8263e in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#5 0x00007fff70d8304a in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#6 0x00007fff70d83d1d in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#7 0x00007fff70d83e89 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#8 0x00007ffff7bbd6db in start_thread (arg=0x7fff4affd700) at pthread_create.c:463
#9 0x00007ffff78e688f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
So the problem seems to be something related to cv2 if I uderstood the output correctly.
I am not sure if it is valid to say that, but the logs printed using Python Logging stop when I call a function from the module Albumentations which kinda makes sense since they use OpenCV.
The code I am using from Albumentations is this (not sure if it helps):
import cv2
from albumentations import ElasticTransform, GridDistortion, OneOf, Compose
import logging
class DataAug:
def __init__(self):
self.logger = logging.getLogger(__name__)
@staticmethod
def get_augs():
grid = GridDistortion(
distort_limit=0.2,
interpolation=cv2.INTER_NEAREST,
border_mode=cv2.BORDER_CONSTANT,
value=0,
always_apply=True
)
elast = ElasticTransform(
alpha_affine=20,
interpolation=cv2.INTER_NEAREST,
border_mode=cv2.BORDER_CONSTANT,
value=0,
always_apply=True
)
return OneOf([
OneOf([grid, elast], p=1),
Compose([grid, elast], p=1)
], p=1)
def apply(self, image, mask):
data = {
'image': image.astype('uint8'),
'mask': mask.astype('uint8')
}
aug = self.get_augs()
self.logger.debug('Apply augmentations')
res = aug(**data)
return res['image'], res['mask']
The last line printed to the log file is the Apply augmentations
.
Is there any other method to better identify what could be the problem causing segmentation fault? Is it actually a problem with the module or am I doing something wrong that is causing it?
EDIT:
Changing the apply
method to this does not fix the problem
def apply(self, image, mask):
aug = self.get_augs()
self.logger.debug('Apply augmentations')
res = aug(image=image.astype('uint8'), mask=mask.astype('uint8'))
return res['image'], res['mask']
EDIT: Another thing I noticed is the seg fault only happens when I am loading pickle files instead of creating the objects in code. I do this to avoid applying this process everytime to save time the next execution.
EDIT: Minimal Reproducible Example (seg fault might not happen on every execution, out of 21 executions, 8 were seg fault)
import pickle
import cv2
import numpy as np
from albumentations import ElasticTransform, GridDistortion, OneOf, Compose
class DataAug:
@staticmethod
def get_augs():
grid = GridDistortion(
distort_limit=0.2,
interpolation=cv2.INTER_NEAREST,
border_mode=cv2.BORDER_CONSTANT,
value=0,
always_apply=True
)
elast = ElasticTransform(
alpha_affine=20,
interpolation=cv2.INTER_NEAREST,
border_mode=cv2.BORDER_CONSTANT,
value=0,
always_apply=True
)
return OneOf([
OneOf([grid, elast], p=1),
Compose([grid, elast], p=1)
], p=1)
def apply(self, image, mask):
data = {
'image': image.astype('uint8'),
'mask': mask.astype('uint8')
}
aug = self.get_augs()
res = aug(**data)
return res['image'], res['mask']
if __name__ == '__main__':
prc_path = {
"a": "test-seg-fault/a",
"b": "test-seg-fault/b"
}
sid = 'test1'
with open(f'{prc_path["a"]}/{sid}', 'wb') as f:
pickle.dump(np.zeros((1, 512, 512, 3)), f)
with open(f'{prc_path["b"]}/{sid}', 'wb') as f:
pickle.dump(np.zeros((1, 512, 512, 1)), f)
with open(f'{prc_path["a"]}/{sid}', 'rb') as f:
input_a = pickle.load(f)
with open(f'{prc_path["b"]}/{sid}', 'rb') as f:
input_b = pickle.load(f)
image, mask = DataAug().apply(image=input_a[0, :, :, :], mask=input_b[0, :, :, 0])
print(image.shape, mask.shape)
The backtrace of the Minimal Reproducible Example:
Thread 31 "python" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffa8dd3700 (LWP 28584)]
__GI___libc_free (mem=0x10035) at malloc.c:3103
3103 malloc.c: No such file or directory.
(gdb) backtrace
#0 __GI___libc_free (mem=0x10035) at malloc.c:3103
#1 0x00007ffff5214a39 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#2 0x00007ffff4e8bef5 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#3 0x00007ffff558c6c5 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#4 0x00007ffff52d463e in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#5 0x00007ffff52d504a in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#6 0x00007ffff52d5d1d in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#7 0x00007ffff52d5e89 in ?? () from /<miniconda env path>/lib/python3.6/site-packages/cv2/cv2.cpython-36m-x86_64-linux-gnu.so
#8 0x00007ffff7bbd6db in start_thread (arg=0x7fffa8dd3700) at pthread_create.c:463
#9 0x00007ffff78e688f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
EDIT:
Removing the dump and pickle read and declaring the variables input_a = np.zeros((1, 512, 512, 3))
, input_b = np.zeros((1, 512, 512, 1))
segmentations fault still happens.