Fixes issue where a partial write can corrupt the database

This commit is contained in:
tidwall 2021-04-01 10:23:25 -07:00
parent a41516f180
commit b6a74904ab
1 changed files with 19 additions and 1 deletions

View File

@ -1176,7 +1176,25 @@ func (tx *Tx) Commit() error {
// Flushing the buffer only once per transaction. // Flushing the buffer only once per transaction.
// If this operation fails then the write did failed and we must // If this operation fails then the write did failed and we must
// rollback. // rollback.
if _, err = tx.db.file.Write(tx.db.buf); err != nil { var n int
n, err = tx.db.file.Write(tx.db.buf)
if err != nil {
if n > 0 {
// There was a partial write to disk.
// We are possibly out of disk space.
// Delete the partially written bytes from the data file by
// seeking to the previously known position and performing
// a truncate operation.
// At this point a syscall failure is fatal and the process
// should be killed to avoid corrupting the file.
pos, err := tx.db.file.Seek(-int64(n), 1)
if err != nil {
panic(err)
}
if err := tx.db.file.Truncate(pos); err != nil {
panic(err)
}
}
tx.rollbackInner() tx.rollbackInner()
} }
if tx.db.config.SyncPolicy == Always { if tx.db.config.SyncPolicy == Always {