8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Fixed #8048: Crash with SIGBUS when there is no free space on the partition with memory-mapped files (#8051)

* 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
This commit is contained in:
Dmitry Starodubov 2024-03-25 17:20:46 +03:00 committed by GitHub
parent b1ba8594ee
commit 1844491fd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

64
src/common/isc_sync.cpp Normal file → Executable file
View File

@ -1178,6 +1178,56 @@ void SharedMemoryBase::unlinkFile(const TEXT* expanded_filename) noexcept
#ifdef UNIX
static inline void reportError(const char* func, CheckStatusWrapper* statusVector)
{
if (!statusVector)
system_call_failed::raise(func);
else
error(statusVector, func, errno);
}
bool allocFileSpace(int fd, off_t offset, FB_SIZE_T length, CheckStatusWrapper* statusVector)
{
#if defined(HAVE_LINUX_FALLOC_H) && defined(HAVE_FALLOCATE)
if (fallocate(fd, 0, offset, length) == 0)
return true;
if (errno != EOPNOTSUPP && errno != ENOSYS)
{
reportError("fallocate", statusVector);
return false;
}
// fallocate is not supported by this kernel or file system
// take the long way around
#endif
static const FB_SIZE_T buf128KSize = 131072;
HalfStaticArray<UCHAR, BUFFER_LARGE> buf;
const FB_SIZE_T bufSize = length < buf128KSize ? length : buf128KSize;
memset(buf.getBuffer(bufSize), 0, bufSize);
os_utils::lseek(fd, LSEEK_OFFSET_CAST offset, SEEK_SET);
while (length)
{
const FB_SIZE_T cnt = length < bufSize ? length : bufSize;
if (write(fd, buf.begin(), cnt) != (ssize_t) cnt)
{
reportError("write", statusVector);
return false;
}
length -= cnt;
}
if (fsync(fd))
{
reportError("fsync", statusVector);
return false;
}
return true;
}
void SharedMemoryBase::internalUnmap()
{
if (sh_mem_header)
@ -1313,7 +1363,10 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
if (mainLock->setlock(&statusVector, FileLock::FLM_TRY_EXCLUSIVE))
{
if (trunc_flag)
{
FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), length));
allocFileSpace(mainLock->getFd(), 0, length, NULL);
}
if (callback->initialize(this, true))
{
@ -2446,8 +2499,19 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector, ULONG new_len
}
if (flag)
{
FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), new_length));
if (new_length > sh_mem_length_mapped)
{
if (!allocFileSpace(mainLock->getFd(), sh_mem_length_mapped,
new_length - sh_mem_length_mapped, statusVector))
{
return false;
}
}
}
MemoryHeader* const address = (MemoryHeader*) os_utils::mmap(0, new_length,
PROT_READ | PROT_WRITE, MAP_SHARED, mainLock->getFd(), 0);