Size: a a a

Rust — русскоговорящее сообщество

2021 June 26

Э

Эрик in Rust — русскоговорящее сообщество
Нет такого, насколько мне известно.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Футуры могут кенсельнуться в самый неподходящий момент.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Проще всего тупо не кенселить их.
источник

n

n1 in Rust — русскоговорящее сообщество
Общая идея-то мне понятна (с прерыванием потока исполнения)

Пересмотрел пример и теперь не понимаю в чем там ошибка?

Вот код

async fn parse_line(socket: &TcpStream) -> Result<String, Error> {
   let len = socket.read_u32().await?; (1)
   let mut line = vec![0; len];
   socket.read_exact(&mut line).await?; (2)
   let line = str::from_utf8(line)?;
   Ok(line)
}


В (2) считается же тот
объём данных, что был доступен в (1), почему разрыв в строке получается? Много данных за раз считывается?
источник

Э

Эрик in Rust — русскоговорящее сообщество
Это хардкорная фигня, тут проще всего прочитать про "panic safety". Кенселинг — это тот же самый panic safety, только в другой обёртке.

Но если ты хочешь объяснения, то у тебя (1) вызывается два раза подряд из-за кенсела первой футуры, но твой код ожидает, что каждый вызов (1) будет в паре с вызовом (2).
источник

Э

Эрик in Rust — русскоговорящее сообщество
Если бы у тебя футура не кенселилась никогда (или кенселилась только когда у тебя вся программа умирает), у тебя тут проблем бы не было.
источник

n

n1 in Rust — русскоговорящее сообщество
Так .await? не вернёт разве ошибку? Т.е. тут больше graceful shutdown?
источник

TK

Traveller Kolsky in Rust — русскоговорящее сообщество
Видимо, с какого-то перепугу авейт на 2 пендится, с размером принимаемых данных как-то связано раз. Мол, где-то ещё есть ссылка на сокет, которая читает из tcpstream. Так предположил.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Ну и я не уверен, что понятно объяснил, потому что чтобы понять эту херню, надо знать про то, как выглядят футуры. Проще всего реально узнать про "panic safety", а потом предполагать, что в любом await у тебя может эта херня запаниковать, а потом закетчиться (ну, собственно, кенсел футуры так примерно и делает).
источник
2021 June 27

Э

Эрик in Rust — русскоговорящее сообщество
Нет, кенселинг футуры, говорю же. Хардкорная херня, надо знать как футуры работают, чтобы понять что именно тут не так, поэтому проще всего тупо не кенселить футуры.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Нет, ты тоже не в ту сторону смотришь. У нас код выглядит как обычный растовый код, но на самом деле на любой await надо смотреть как на херню, у которой внутри panic при кенселе вызывается, а на любой селект надо смотреть как на catch_unwind, который ловит эти паники после кенсела.
источник

TK

Traveller Kolsky in Rust — русскоговорящее сообщество
Так чему там паниковать-то? Или кенселить? Пример вроде простой.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Ну то есть там на самом деле не паники, а кенсел, но я не знаю как это объяснить человеку, который не прочитал гигантскую статью про то, как на самом деле в расте устроены футуры.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Просто прочитай "panic safety", там всё относительно просто написано про валидность стейта структур, а потом подумай про валидность TpcStream, на который мы вызвали read_u32 два раза подряд.
источник

TK

Traveller Kolsky in Rust — русскоговорящее сообщество
Но почему он зовётся два раза подряд? Авейт же один.
источник

Э

Эрик in Rust — русскоговорящее сообщество
Ну то есть давай перепишем эту функцию на обычный растовый код из асинка:

fn parse_line(socket: &TcpStream, cancel_flag: Cell<bool>) -> Result<String, Error> {
   let len = if cancel_flag.get() { panic!() } else { socket.read_u32()? }; // (1)
   let mut line = vec![0; len];
   if cancel_flag.get() { panic!() } else { socket.read_exact(&mut line)? }; // (2)
   let line = str::from_utf8(line)?;
   Ok(line)
}
источник

Э

Эрик in Rust — русскоговорящее сообщество
А теперь поставь вместо селекта какую-нибудь конструкцию, которая ловит первый результат, ставит cancel_flag.set(true) после того как поймает первый результат, а остальные ловит через catch_unwind.
источник

TK

Traveller Kolsky in Rust — русскоговорящее сообщество
Скетчили потом, а дальше что? Выполнение не продолжится с let mut line = ...?
источник

Э

Эрик in Rust — русскоговорящее сообщество
Ну то есть тут всё равно нет нормального примера, если не взять толстые треды, но просто представь, что мы так можем сделать.
источник

Э

Эрик in Rust — русскоговорящее сообщество
И скажи мне, что будет, если мы запаникуем на (2), не прочитав из стрима строку сначала?
источник