Skip to content

Commit 26fcd16

Browse files
Fixed #8048: Crash with SIGBUS when there is no free space on the partition with memory-mapped files (#8053)
* Fixed #8048: Crash with SIGBUS when there is no free space on the partition with memory-mapped files * Postfix for #8048: If "fallocate" is not supported by the filesystem or kernel write zeroes instead of an error
1 parent 17cd224 commit 26fcd16

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/common/isc_sync.cpp

100644100755
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,56 @@ void SharedMemoryBase::unlinkFile(const TEXT* expanded_filename) noexcept
11681168

11691169
#ifdef UNIX
11701170

1171+
static inline void reportError(const char* func, CheckStatusWrapper* statusVector)
1172+
{
1173+
if (!statusVector)
1174+
system_call_failed::raise(func);
1175+
else
1176+
error(statusVector, func, errno);
1177+
}
1178+
1179+
bool allocFileSpace(int fd, off_t offset, FB_SIZE_T length, CheckStatusWrapper* statusVector)
1180+
{
1181+
#if defined(HAVE_LINUX_FALLOC_H) && defined(HAVE_FALLOCATE)
1182+
if (fallocate(fd, 0, offset, length) == 0)
1183+
return true;
1184+
1185+
if (errno != EOPNOTSUPP && errno != ENOSYS)
1186+
{
1187+
reportError("fallocate", statusVector);
1188+
return false;
1189+
}
1190+
// fallocate is not supported by this kernel or file system
1191+
// take the long way around
1192+
#endif
1193+
static const FB_SIZE_T buf128KSize = 131072;
1194+
HalfStaticArray<UCHAR, BUFFER_LARGE> buf;
1195+
const FB_SIZE_T bufSize = length < buf128KSize ? length : buf128KSize;
1196+
1197+
memset(buf.getBuffer(bufSize), 0, bufSize);
1198+
os_utils::lseek(fd, LSEEK_OFFSET_CAST offset, SEEK_SET);
1199+
1200+
while (length)
1201+
{
1202+
const FB_SIZE_T cnt = length < bufSize ? length : bufSize;
1203+
if (write(fd, buf.begin(), cnt) != (ssize_t) cnt)
1204+
{
1205+
reportError("write", statusVector);
1206+
return false;
1207+
}
1208+
length -= cnt;
1209+
}
1210+
1211+
if (fsync(fd))
1212+
{
1213+
reportError("fsync", statusVector);
1214+
return false;
1215+
}
1216+
1217+
return true;
1218+
}
1219+
1220+
11711221
void SharedMemoryBase::internalUnmap()
11721222
{
11731223
if (sh_mem_header)
@@ -1303,7 +1353,10 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
13031353
if (mainLock->setlock(&statusVector, FileLock::FLM_TRY_EXCLUSIVE))
13041354
{
13051355
if (trunc_flag)
1356+
{
13061357
FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), length));
1358+
allocFileSpace(mainLock->getFd(), 0, length, NULL);
1359+
}
13071360

13081361
if (callback->initialize(this, true))
13091362
{
@@ -2436,8 +2489,19 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector, ULONG new_len
24362489
}
24372490

24382491
if (flag)
2492+
{
24392493
FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), new_length));
24402494

2495+
if (new_length > sh_mem_length_mapped)
2496+
{
2497+
if (!allocFileSpace(mainLock->getFd(), sh_mem_length_mapped,
2498+
new_length - sh_mem_length_mapped, statusVector))
2499+
{
2500+
return false;
2501+
}
2502+
}
2503+
}
2504+
24412505
MemoryHeader* const address = (MemoryHeader*) os_utils::mmap(0, new_length,
24422506
PROT_READ | PROT_WRITE, MAP_SHARED, mainLock->getFd(), 0);
24432507

0 commit comments

Comments
 (0)