Я бы тут хотел не спорить о терминах, а разделить выделение/освобождение ресурса (в данном случае, сокета) и управление состоянием этого ресурса.
Некоторую путаницу в POSIX вносит то, что выделенный но не присоединенный сокет - штука довольно бесполезная, а close объединяет семантику закрытия соединения и освобождения дескриптора.
В этом смысле Go и Plan9 более последовательны, net.Dial и dial основременно создают объект и устанавливают соединение (но усложняют настройку сокета, которую хотелось бы сделать до попытки установления соединения).
Там очень много технических подробностей, но суть примерно такая.
Среде исполнения Go время от времени надо за какой-нибудь надобностью пробежаться по стекам гороутин. Например, такая потребность возникает при обработке panic. Сборщик мусора тоже так делает, чтобы поискать на стеке валидные указатели и не освободить случайно объекты, на которые они указывают.
Код, который пробегается по стеку, рассчитывает на то, что в указателе стека всегда лежит корректное значение.
При входе в функцию стек растёт, при выходе уменьшается. И делается это, естественно, командами процессора.
Особенностью архитектуры ARM64 является то, что при определенных условиях эти манипуляции со стеком раскладывались компилятором на две команды. И в тот очень короткий промежуток времени, когда первая из этих команд уже выполнилась, а вторая - еще нет, указатель стека был очень ненадолго невалидным.
Если именно в этот момент среде исполнения понадобится размотать стек именно этой гороутины, то случится беда и всё сломается.
Поскольку опасное состояние длится очень недолго, попасть именно на этот момент сложно, и проблема возникает редко. Однако при определенных патернах загрузки она всё же воспроизводится.
Вот, ребята докопались до причины и даже написали простенький тест, который устойчиво воспроизводил проблему, а разработчики компилятора починили компилятор.
Если вы создали сокет, попытались его открыть и отвалились по таймауту - не переиспользуйте его! Для новой попытки обязательно создавайте новый сокет!
Я дико извиняюсь, но создание сокета (вызовом socket) - это и есть его открытие. Что открыли, то надо закрыть.
А connect - это не открытие сокета, а установление соединения - действие, которое пытается изменить состояние сокета, но не открывает и не закрывает его.
Именно здесь семантический переход от «вакансии» к «позиции» перестает быть лингвистическим нюансом и становится механизмом психологической компенсации. Там, где исчезает объективная социальная ценность труда, язык предлагает суррогат значимости через переопределение базовых понятий.
Во-во. Механизмом психологической компенсации.
По сути, ничего не изменилось. Нанятый работник как был винтиком в механизме, так им и остался. И отчуждение результатов труда никуда не делось.
Только теперь работникам льют психологическую лапшу на уши. Ты, типа, не просто таски закрываешь в джире, а командный игрок, личность в процессе самореализации. Гордись тем, что тебя взяли в такую крутую команду, в которую берут не только лишь всех и что ты не просто делаешь костыли в выкаченном из интернета говнокоде, а определяешь светлое технологическое будущее компании.
Да еще и научились вместо денег давать "социальный пакет". Зарплату мы тебе не подымем, но зато ДМС, фитнес и раз в год от компании - фирменная маечка (и фирменная кружка в день первого выхода на работу, чтобы было в чём заваривать чай из дешевого пакетика, когда на нормальный обед сбегать некогда).
Придумали, конечно. ABNF, например, и всякое такое.
Вопрос, почему пользователи предпочитают неудобоваримые регулярки вместо более понятных инструментов.
Регулярки хороши, чтобы разбивать текст на лексемы, и классический парсер, он двухуровневый: лексемы выделяются регулярными выражениями, потом делается уже синтаксический анализ по грамматике, описанной каким-нибудь вариантом BNF (Backus–Naur form)
В RFC5822, на который вы ссылаетесь, address определён со всеми этими наворотами, а то, что имеете ввиду вы, это кусок адреса, addr-spec.
Более того, RFC6068, определяющий схему mailto, специально оговаривает, что address, это как в RFC5822, со следующими оговорками: (...), фактически сводя address к addr-spec.
addr-spec, наверное да, регулярен. Но со всеми интернационализационными наворотами это не точно.
Я не смог придумать, как сделать парсер, который обходится без backtracking. Когда парсер только прочёл слово Vasya, он не может знать, какой из двух вариантов используется.
Регулярки, которые умеют в обратные ссылки (backreference) не являются регулярными грамматиками по Хомскому и не могут быть преобразованы в регулярный ДКА. Наверное, есть граждане, которым обратные ссылки действительно нужны...
С другой стороны, синтаксис e-mail адреса (per RFC 822) не описывается регулярной грамматикой...
P.S. У Go реализация регулярных выражений из стандартной библиотеки гарантирует, что время сопоставления растёт, как O(n), где n - размер входного текста.
Теперь вся логика кормления находится в одном месте. Если вы захотите что-то изменить, правка в одной функции отразится на всех ее вызовах. Код стал короче, чище и надежнее. Избегание дублирования - один из ключевых принципов хорошего программирования. И коты довольны, и код хороший. Одни плюсы ведь.
У этой палки есть и обратная сторона.
Если имеются разумные причины предполагать, что рацион и способ кормления Барсика и Мурзика совпали на 100% случайно и в перспективе могут разъехаться, то копипаста может оказаться даже и надежнее. Например, если Барсику доктор пропишет слабительное, а Мурзику гипералергенный сухой корм, то как бы общая процедура чего не перепутала.
Да-да, точно. Поскольку контроллер клавиатуры всегда присутствовал и, будучи однокристаллкой, обладал некоторым разумом, то функция дёргать ресет по команде возлагалась именно на него.
Не надо думать, что сейчас прям прогресс с теми временами. System Management Mode, которая низкоуровневее/приоритетнее, чем операционная система мне тоже не представляется таким уж и красивым архитектурным решением.
У 80286 была забавная особенность: у него была команда, которая включала защищённый режим, но не было команды, которая его выключала. А без использования защищенного режима он мог физически адресовать только 1M + 64K памяти.
MS-DOS уже и в те времена мог с пользой распоряжаться памятью за пределами 1M. Например, туда можно было положить дисковый кэш, или виртуальный RAM-диск. Некоторые программы умели входить в защищенный режим и жить, как белые люди, пользуясь всей физически доступной памятью.
Проблема выхода из защищенного режима решалась физическим ресетом процессора. Там где-то в BIOS-е можно было пометить, что делать сразу после ресета: уходить на нормальную загрузку или "вернуться" в real mode без перезагрузки компьютера. Соответственно, все программы, которые пользовались защищенным режимом, возвращались назад с помощью именно этого механизма.
Потом появился 80386, он умел выходить из защищенного режима с помощью соответствующей команды (и еще много чего другого полезного умел).
80186 позиционировался на рынок embedded устройств и был для него удобнее, чем 8086, благодаря тому, что часть функций чипсета реализовалась самим процессором
Но в те времена редко кто делал ембедщину на настолько мощном (по тем временам) процессоре, так что очень уж популярным он не стал.
Я им кой-чего понапрограммировал, чего ни у кого не было, они там ездили, на выставках показывали и инвесторам, а со мной всё не торопились расплачиваться.
Потом у меня произошёл довольно долгий и неприятный разговор с ихним CTO, которых был бывший наш гражданин, и он стал со мной торговаться, пытаясь снизить изначально оговорённую цену.
Разговор кончился на повышенных тонах, и в конце концов я заявил, что меня вполне устроит, если они вообще ничего не заплатят и перестанут пользоваться моим кодом, на который у них права ниоткуда не возникают, кроме как из закрытого контракта со мной. Ихний CTO пытался меня пугать, что они просто переведут сумму (меньше начальной договорённости) на мой счет и договор тем самым закроют, на что я сказал, что сообщу своему банку, что я не знаю, что это за перевод такой, наверное перевели по ошибке и я тут не при чём.
В общем, через 5 минут позвонил ихний CEO-индус, и мы обо всём с ним мило договорились. А еще через 5 минут и денежки пришли.
Судиться с ними в американском суде мне было, понятно, не с руки, но и им было стрёмно строить свой бизнес, не имея внятных прав на ключевую технологию. К тому же сумма по ихним меркам была совсем не такая уж и большая, чтобы ради нее так рисковать.
Я бы тут хотел не спорить о терминах, а разделить выделение/освобождение ресурса (в данном случае, сокета) и управление состоянием этого ресурса.
Некоторую путаницу в POSIX вносит то, что выделенный но не присоединенный сокет - штука довольно бесполезная, а close объединяет семантику закрытия соединения и освобождения дескриптора.
В этом смысле Go и Plan9 более последовательны, net.Dial и dial основременно создают объект и устанавливают соединение (но усложняют настройку сокета, которую хотелось бы сделать до попытки установления соединения).
Там очень много технических подробностей, но суть примерно такая.
Среде исполнения Go время от времени надо за какой-нибудь надобностью пробежаться по стекам гороутин. Например, такая потребность возникает при обработке panic. Сборщик мусора тоже так делает, чтобы поискать на стеке валидные указатели и не освободить случайно объекты, на которые они указывают.
Код, который пробегается по стеку, рассчитывает на то, что в указателе стека всегда лежит корректное значение.
При входе в функцию стек растёт, при выходе уменьшается. И делается это, естественно, командами процессора.
Особенностью архитектуры ARM64 является то, что при определенных условиях эти манипуляции со стеком раскладывались компилятором на две команды. И в тот очень короткий промежуток времени, когда первая из этих команд уже выполнилась, а вторая - еще нет, указатель стека был очень ненадолго невалидным.
Если именно в этот момент среде исполнения понадобится размотать стек именно этой гороутины, то случится беда и всё сломается.
Поскольку опасное состояние длится очень недолго, попасть именно на этот момент сложно, и проблема возникает редко. Однако при определенных патернах загрузки она всё же воспроизводится.
Вот, ребята докопались до причины и даже написали простенький тест, который устойчиво воспроизводил проблему, а разработчики компилятора починили компилятор.
А что, в среде исполнения Питона каким-то волшебным образом нет ошибок? :)
Я дико извиняюсь, но создание сокета (вызовом socket) - это и есть его открытие. Что открыли, то надо закрыть.
А connect - это не открытие сокета, а установление соединения - действие, которое пытается изменить состояние сокета, но не открывает и не закрывает его.
Во-во. Механизмом психологической компенсации.
По сути, ничего не изменилось. Нанятый работник как был винтиком в механизме, так им и остался. И отчуждение результатов труда никуда не делось.
Только теперь работникам льют психологическую лапшу на уши. Ты, типа, не просто таски закрываешь в джире, а командный игрок, личность в процессе самореализации. Гордись тем, что тебя взяли в такую крутую команду, в которую берут не только лишь всех и что ты не просто делаешь костыли в выкаченном из интернета говнокоде, а определяешь светлое технологическое будущее компании.
Да еще и научились вместо денег давать "социальный пакет". Зарплату мы тебе не подымем, но зато ДМС, фитнес и раз в год от компании - фирменная маечка (и фирменная кружка в день первого выхода на работу, чтобы было в чём заваривать чай из дешевого пакетика, когда на нормальный обед сбегать некогда).
Придумали, конечно. ABNF, например, и всякое такое.
Вопрос, почему пользователи предпочитают неудобоваримые регулярки вместо более понятных инструментов.
Регулярки хороши, чтобы разбивать текст на лексемы, и классический парсер, он двухуровневый: лексемы выделяются регулярными выражениями, потом делается уже синтаксический анализ по грамматике, описанной каким-нибудь вариантом BNF (Backus–Naur form)
Можно упростить. Там в целом довольно понятная алгоритмика, хоть аккуратно её реализовать - муторно, аж жуть :)
В RFC5822, на который вы ссылаетесь,
addressопределён со всеми этими наворотами, а то, что имеете ввиду вы, это кусок адреса,addr-spec.Более того, RFC6068, определяющий схему
mailto, специально оговаривает, чтоaddress, это как в RFC5822, со следующими оговорками: (...), фактически сводяaddressкaddr-spec.addr-spec, наверное да, регулярен. Но со всеми интернационализационными наворотами это не точно.Примеры валидных адресов:
есть варианты и позаковыристее. Не надо думать, что e-mail address, это только user@example.com
Более того, есть две формы адреса:
Я не смог придумать, как сделать парсер, который обходится без backtracking. Когда парсер только прочёл слово Vasya, он не может знать, какой из двух вариантов используется.
Регулярки, которые умеют в обратные ссылки (backreference) не являются регулярными грамматиками по Хомскому и не могут быть преобразованы в регулярный ДКА. Наверное, есть граждане, которым обратные ссылки действительно нужны...
С другой стороны, синтаксис e-mail адреса (per RFC 822) не описывается регулярной грамматикой...
Я просто оставлю это здесь:
Russ Cox. Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...)
P.S. У Go реализация регулярных выражений из стандартной библиотеки гарантирует, что время сопоставления растёт, как O(n), где n - размер входного текста.
Что такое КИС?
У этой палки есть и обратная сторона.
Если имеются разумные причины предполагать, что рацион и способ кормления Барсика и Мурзика совпали на 100% случайно и в перспективе могут разъехаться, то копипаста может оказаться даже и надежнее. Например, если Барсику доктор пропишет слабительное, а Мурзику гипералергенный сухой корм, то как бы общая процедура чего не перепутала.
Коты в среднем не одинаковые.
Не, ну я так не играю!
И хде?
Да-да, точно. Поскольку контроллер клавиатуры всегда присутствовал и, будучи однокристаллкой, обладал некоторым разумом, то функция дёргать ресет по команде возлагалась именно на него.
Не надо думать, что сейчас прям прогресс с теми временами. System Management Mode, которая низкоуровневее/приоритетнее, чем операционная система мне тоже не представляется таким уж и красивым архитектурным решением.
У 80286 была забавная особенность: у него была команда, которая включала защищённый режим, но не было команды, которая его выключала. А без использования защищенного режима он мог физически адресовать только 1M + 64K памяти.
MS-DOS уже и в те времена мог с пользой распоряжаться памятью за пределами 1M. Например, туда можно было положить дисковый кэш, или виртуальный RAM-диск. Некоторые программы умели входить в защищенный режим и жить, как белые люди, пользуясь всей физически доступной памятью.
Проблема выхода из защищенного режима решалась физическим ресетом процессора. Там где-то в BIOS-е можно было пометить, что делать сразу после ресета: уходить на нормальную загрузку или "вернуться" в real mode без перезагрузки компьютера. Соответственно, все программы, которые пользовались защищенным режимом, возвращались назад с помощью именно этого механизма.
Потом появился 80386, он умел выходить из защищенного режима с помощью соответствующей команды (и еще много чего другого полезного умел).
80186 позиционировался на рынок embedded устройств и был для него удобнее, чем 8086, благодаря тому, что часть функций чипсета реализовалась самим процессором
Но в те времена редко кто делал ембедщину на настолько мощном (по тем временам) процессоре, так что очень уж популярным он не стал.
У меня был как-то сложный заказчик
Я им кой-чего понапрограммировал, чего ни у кого не было, они там ездили, на выставках показывали и инвесторам, а со мной всё не торопились расплачиваться.
Потом у меня произошёл довольно долгий и неприятный разговор с ихним CTO, которых был бывший наш гражданин, и он стал со мной торговаться, пытаясь снизить изначально оговорённую цену.
Разговор кончился на повышенных тонах, и в конце концов я заявил, что меня вполне устроит, если они вообще ничего не заплатят и перестанут пользоваться моим кодом, на который у них права ниоткуда не возникают, кроме как из закрытого контракта со мной. Ихний CTO пытался меня пугать, что они просто переведут сумму (меньше начальной договорённости) на мой счет и договор тем самым закроют, на что я сказал, что сообщу своему банку, что я не знаю, что это за перевод такой, наверное перевели по ошибке и я тут не при чём.
В общем, через 5 минут позвонил ихний CEO-индус, и мы обо всём с ним мило договорились. А еще через 5 минут и денежки пришли.
Судиться с ними в американском суде мне было, понятно, не с руки, но и им было стрёмно строить свой бизнес, не имея внятных прав на ключевую технологию. К тому же сумма по ихним меркам была совсем не такая уж и большая, чтобы ради нее так рисковать.