Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
impl Drop for FileDesc {
fn drop(&mut self) {
// Note that errors are ignored when closing a file descriptor. The
// reason for this is that if an error occurs we don't actually know if
// the file descriptor was closed or not, and if we retried (for
// something like EINTR), we might close another valid file descriptor
// opened after we closed ours.
let _ = unsafe { libc::close(self.fd) };
}
}
> как вернуть юзеру информацию о неудачном закрытии
Сделать явный close(), commit() или что там по смыслу подходит твоему коду и всегда вызывать его в конце успешной ветки. Там ты сможешь вернуть ошибку если что-то недофлашилось. А если дело до деструктора дойдёт -- забить хер на ошибку.
Лол, уже второй язык, который на close() обосрался... В джаве тоже некоторые обёртки над стримом проглатывали исключение и оставляли закоррапченный файл.
зацени лучше вот это: петухи из постгреса кукарекают что они наплодили процессов и почему-то - почему же??? - фсинк проваливается в одном, а другой об этом не знает
А разве нет? Там вроде глубже проблема, что рандомная прога или даже само ядро может случайно триггернуть флаш страничек твоего файла и обосраться, а потом fsync молча скажет, что всё заебись.
Насколько понимаю, внутри одного процесса такого произойти не может. Они жалуются, что форкаются и шарят дескрипторы, только вот же ведь дела, процессы-то разные.
Там вот такой паттерн получается, если я правильно понял:
1) Открываем файл, пишем туда, успешно закрываем обычным close()
2) Через какое-то время ядро в фоне флашит буфера на диск, получает ошибку записи и забивает на неё
3) Открываем файл, пишем туда, делаем fsync() и close()
4) fsync() успешен, файл в середине запорот, профит!
Т.е. вроде бы и косяк постгри, что файл заново переоткрыли. А с другой стороны возникает вопрос -- а не возникнет ли такая ситуация и без переоткрытия?
> а не возникнет ли такая ситуация и без переоткрытия
Ну т.е. к примеру:
1) Открываем файл, пишем туда, держим его открытым ещё час-другой
2) Через какое-то время ядро флашит буфера на диск, получает ошибку записи
3) Зовём fsync()
Есть ли гарантия, что fsync() зарепортит нам ошибку из пункта 2?
Помнится мне, как я измученный транслитом, я на уроке англиячьего прочел слово "yellow" как "уэллоу",
чем вызвал неодобрительный взгляд училки. Она меня еще и передразнила.
> внутри одного процесса такого произойти не может
Да нихуя... Проблема, которую в ядре 4.13 фиксили, стреляла и для процессов и для тредов и даже в однопоточной хуйне. Если джва хендла работали с разными кусками одного и того же файла, то они могли зафлашить чужой кусок и обработать его ошибку. Теперь ошибку от write-back кеша получают все заинтересованные, а не только первый.
Постгресовая бага в общем-то тоже от тредов/процессов не зависит. Если ты файл закрыл, то потом переоткрывать его и флашить уже поздно. Ядро трекает ошибки только для открытых хендлов, на заброшенные ему похуй.
Окей, не одного процесса, одного хендла. Я в общем не вижу почему с файлом должен работать один контекст, а ошибки за него ловить второй. По мне так это наоборот корректное поведение.
Ну жопа в том, что fsync() весь файл флашит, не только записанные через твой хендл куски. Т.е. чужие ошибки ты в любом случае будешь получать. Просто теперь есть гарантия, что ты свои не проебёшь из-за соседа.
А работать с одним файлом через несколько хендлов в разных потоках/процессах -- вполне норм для СУБД, имхо. В прыщах же один хендл не получится юзать для параллельных записей.
Ну, кстати, у std::fs::File есть sync_all (аля fsync) и sync_data (аля fdatasync). И там даже в доке написано, что деструктор может молча проебсти данные, надо юзать эти sync в конце успешной ветки.
Call File::sync_data or File::sync_all if you want to do your best to ensure that all of the data has been written fully through to the disk.
These are very expensive operations, so we don't call them automatically. Code that needs to make guarantees about data consistency should use them as necessary.
Пиздец у них двоемыслие, как-будто разные люди писали разные фрагменты этого кода, не общаясь друг с другом... А вытащить дескриптор и позвать close() ты не можешь т.к. они потом тоже безусловно позовут в деструкторе и закроют что-то левое? Ну тогда остаётся свою обёртку писать.
> very expensive
Ну... это реальная цена записи на диск, не более того. По сравнению с читерской записью во write-back кеш дорого, конечно.
Сделать явный close(), commit() или что там по смыслу подходит твоему коду и всегда вызывать его в конце успешной ветки. Там ты сможешь вернуть ошибку если что-то недофлашилось. А если дело до деструктора дойдёт -- забить хер на ошибку.
Х.з. как ещё это решить.
З.Ы. С возвращением!
https://mydbanotebook.org/post/fsync/
https://postgrespro.com/list/thread-id/2379543
а виновато конечно ядро, а не ебанарии, отказывающиеся мерджить поддержку int64 в 2021
А разве нет? Там вроде глубже проблема, что рандомная прога или даже само ядро может случайно триггернуть флаш страничек твоего файла и обосраться, а потом fsync молча скажет, что всё заебись.
1) Открываем файл, пишем туда, успешно закрываем обычным close()
2) Через какое-то время ядро в фоне флашит буфера на диск, получает ошибку записи и забивает на неё
3) Открываем файл, пишем туда, делаем fsync() и close()
4) fsync() успешен, файл в середине запорот, профит!
Т.е. вроде бы и косяк постгри, что файл заново переоткрыли. А с другой стороны возникает вопрос -- а не возникнет ли такая ситуация и без переоткрытия?
Ну т.е. к примеру:
1) Открываем файл, пишем туда, держим его открытым ещё час-другой
2) Через какое-то время ядро флашит буфера на диск, получает ошибку записи
3) Зовём fsync()
Есть ли гарантия, что fsync() зарепортит нам ошибку из пункта 2?
Т.е. эту часть всё-таки пофиксили и такая гарантия есть. Если ядро свежее 2017 года.
ну мы же говорим про постгрес
там реально люди в каком-то 99 живут
чем вызвал неодобрительный взгляд училки. Она меня еще и передразнила.
Да нихуя... Проблема, которую в ядре 4.13 фиксили, стреляла и для процессов и для тредов и даже в однопоточной хуйне. Если джва хендла работали с разными кусками одного и того же файла, то они могли зафлашить чужой кусок и обработать его ошибку. Теперь ошибку от write-back кеша получают все заинтересованные, а не только первый.
Постгресовая бага в общем-то тоже от тредов/процессов не зависит. Если ты файл закрыл, то потом переоткрывать его и флашить уже поздно. Ядро трекает ошибки только для открытых хендлов, на заброшенные ему похуй.
праально
привет
А работать с одним файлом через несколько хендлов в разных потоках/процессах -- вполне норм для СУБД, имхо. В прыщах же один хендл не получится юзать для параллельных записей.
а , всё
у меня тут это
тред не читай
@
сразу отвечай
случился
if the file offset is modified by
using lseek(2) on one of the file descriptors, the offset is also
changed for the other.
Есть мнение, что писать в один и тот же файл из двух разных процессов не очень хорошо.
Хотя конечно в СУБД ты можешь поделить между ними странички
но емнип постгрес как раз всё делит на постраничные файлы...
По сути это файловая система внутри файла (ну вроде тосты отдельно хранятся).
Потому я и сказал, что для СУБД это ОК. А в целом странно.
Кстати, некоторые субд (оракл, MS-SQL) умеют срать на сырые партиции вообще. Странно, что постгря так не умеет.
Да чуваки решили сэкономить на разработке. Типа в ядре должен быть хороший кеш-менеджер, зачем свой писать. Поэтому абузят файлуху в хвост и в гриву.
Так то отдельный раздел и выделенный регион памяти лучше были бы, конечно.
Хвала яхве, что хоть размер их странички кратен размеру страницы памяти
- хрюкнул как myebanoebook
а вроде и не пил сегодня
Ванишед-хуянишед!
ой, это про ВОЗВРАЩЕНИЕ, если что
Call File::sync_data or File::sync_all if you want to do your best to ensure that all of the data has been written fully through to the disk.
These are very expensive operations, so we don't call them automatically. Code that needs to make guarantees about data consistency should use them as necessary.
https://github.com/rust-lang/rust/blob/master/library/std/src/fs.rs#L307
> very expensive
Ну... это реальная цена записи на диск, не более того. По сравнению с читерской записью во write-back кеш дорого, конечно.
Не могу, он приватный
Wir werden angegriffen! Alle posten besetzen. Ich wederchole: wir werden angegriffen!
Мои глаза!!!
Тарас перешёл на дrustню (!) и ностальгирует по Сишке (!!).
> Похуй на ошибки возврата, да?
> это ж Раст, хуй с ними с исключениями короче.
Да, «Си» это не самый хуёвый язык как оказалось.