Re[2]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 10:27
Оценка: 79 (3)
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, samius, Вы писали:


F> Возможно ли такое, что ты сврй подход щаоаенсорсишь и сделаешь нормальное объяснение как этим пользоваться?

Заопенсосить возможно, но маловероятно. Куда вероятнее пост в некроблоге, но тоже, фиг его знает.
F> Смотри — первый бенефит — оно нафиг никому не надо.
F> Второй бенефит — ты потратишь время впустую.
Верно, согласен.
На самом деле опенсорс форма не нужна. Там исходников край 400 линий и их проще вставить в потенциально проблемный проект, чем тащить лишнюю зависимость. Да и есть вопросы с организацией подмены встроенного Monitor. Использование using вместо lock имеет свои недостатки (например, разрешает await внутри блока), требует мотивированного политического решения использовать в прокете именно этот конструкт. Использование lock требует задействования недокументированных возможностей компилятора, да и не известно, как ведет себя при использовании в разных сборках. Скорее всего — никак, т.е. в каждой сборке прокта придется вписывать (или включать исходники) для подмены родного Monitor-а.
Самое ценное здесь — идея. До нее дошел сам, правда, не с нуля. Но на авторство не претендую. Спасибо Sinix-у за ссылку, там идея неплохо описана.

Все что осталось (не тянет на статью) — история того как я дошел, мысли.

F> Механизм используемый тобой слишком слоден доя новичков имхо, но, имхо, на самом деле — твоя практика тут... бесценна. Ты ж ведь из тех кто юзает дотнет почти сгачала если я не ошибаюсь, а вае "знакомство" с Sinix волей судеб случилось токс щас? Хотя это дико — я давно ставлб оценки тока ему и рслн меня режет за межуусобничество — но я его в глаза не знаю...

Да, я юзаю дотнет почти сначала, точнее, с первой общедоступной беты. На rsdn зарегистрировался где-то в 2005 (до этого с годик лишь читал). С Sinix-ом мы пересекаемся часто последние несколько лет (но не регулярно), а "в глаза" я вообще никого не знаю.

F> А и пофиг. Мне всегда на них было пофиг.


F> Просто если есть реально хорошмй опыт — имхо — его стоит описать, тем более если есть примеры.

F> Безусловно — нужно твоё желание, нужно вообще видение этого как статьи. Я лично доя себя понял что вы межлу собой поговорили о чем-то. Не то. Ну не то что-бы у мну фантазия не работала, но это другое.
F> @samius, если ты готов поделиться опытом — я думаю как минимум это оценят даже "смежники", вдобавок задача что ты озвучил — два раза как выбивается в интересные — она ведь из области того запрещённого кода где некоторые считаю что никто кроме... (неважне чего — важен факт).
F> Мне кажется если иы осилишь аггрегировать свой опыт — это было бы интересно.
F> Нафуя? Х.з.

Разве что, ради интереса. На самом деле, оно не каждому и не в каждом проекте нужно.

Итак, вот как было. Году в 2003-м усиленно следил за codeproject.com, и встретил там как раз статью о подмене Monitor (именно той, что в старте топика) для диагностики дедлоков. Статью я уже искал ранее, вот и сейчас не нашел. Там именно что при попытке захвата проверялся граф уже захваченных локов, который при удачном захвате достраивался (через захват глобального синкрута). Это все работало только для дедлоков вида
// thread 1
lock (a)
  lock (b) {}

// thread 2
lock (b)
  lock (a) {}

с поправкой на неопределенную глубину вложений. И при обнаружении дедлока в момент захвата сразу кидается исключение (со стеком и шлюхами). Все круто, исключение вместо зависания — это определенно прогресс. Но дедлок — это такая история, которая может то ли случиться, то ли нет, то ли в этом году, то ли в следующем, то ли на машине разработчика, то ли у юзера, который то ли забьет, то ли нет. На счет этого статья более ничего не предлагала. Тогда я статью почитал и забыл. Больше ее не видел.

История продолжилась пару лет назад, когда в бете текущего проекта искали злой дедлок, который просто вымораживал винду на машинах пользователей. Вспомнил я про ту статью, накидал подобную диагностику, заменил все lock-и на using-и и нифига. Дедлок есть, а исключения — нет. Оказалось, что все последовательности захватов были реализованы верно, но вот был блокирующий вызов проводника и делался он из под захвата. Проводник вызывал приложение и упирался в этот же захват (на самом деле цепочка длинее). Ну да ладно, дедлок нашелся, а прифигаченный контроль отдирать не стал. А контроль потом нет-нет, да и стал срабатывать, преимущественно у пользователей (беты) после фиксов, да дополнений фич, сделанных впопыхах. Так встала задача раннего обнаружения дедлоков, т.е. еще до момента когда появится петля в графе захватов.

Рассуждения следующие: все синкруты в дотнете, которые ходят на Monitor.Enter, равноправны. От этого и проблемы и неопределенности во времени возникновения дедлока. Разработчик каким-то образом представляет правильную последовательность взятия синкрутов своих объектов, но у него нет инструментального контроля проверки этой правильности. Равноправность (следовательно неопределенность последовательности взятия локов) надо исключить. Если нужно взять два равноправных лока, то значит, у этих локов должны быть разные приоритеты их взятия.

Далее есть сценарии, при которых требуется захватить синкруты одного объекта, другого (другого уровня). Либо только одного, либо двух, либо после захвата чего-либо может выясниться, что нужно захватить еще что-то, а может и не выясниться. Исходим из того, что разработчик в курсе, какие бывают проблемы от некорректной последовательности захватов, и может сам корректно определить порядок и записать его в тетрадке, или где-нибудь еще. И написать в склерозник, что при каждом изменении надо удостоверяться в правильности порядка. А вот это проблема. При рефакторинге правильную последовательность легко потерять и узнать об этом в продакшне. Дело за автоматизированной проверкой. А автоматизированная проверкаа она не знает о решениях разработчика про правильную последовательность. И ей остается строить граф и искать петли, что дорого и непродуктивно (результаты анализа нужны сейчас, а не как стрясется дедлок). Значит — надо маркировать синкруты в коде в соответствии с определенным разработчиком порядком правильным порядком захвата. Проще всего — указать level.

Итого, граф с петлями развязал разработчик мысленным усилием. Строить его не нужно, искать петли не нужно, остается лишь проконтроллировать правильность порядка (не давать уменьшать уровень, или увеличивать, в зависимости от того, какое направление уровней задано). Лучше всего, если проверка будет выполняться в compile или около того time-е. Но вот чисто не срослось. Раз у меня уже была вкорячена проверка времени выполнения (петель графов), решено было допилить ее. Точнее, перепилить, т.к. графы больше не нужны.

Пара слов о реализации
синкрут — абстрактный класс с методом получения уровня. Почему абстрактный — у меня их много, раздувать память под хранение поля было дорого. А расходы на косвенность через vtbl — не очень.
[ThreadStatic] поле, указывающее на тредконтекст — экземпляр класса, где определен стек взятых синкрутов (односвязный неизменяемый список {next, value}). А на самом деле вместе с синкрутом в списке на каждый узел хранятся sourceLine, sourcePath, memberName, которые подставляет компилятор). Но они не особо нужны.
При захвате читаем [ThreadStatic], определяем последний взятый синкрут (на вершине стека), сравниваем его уровень с уровнем того, который хотим взять. Если равны — пробегаем по стеку взятых рутов с проверкой, а нет ли среди них того, который хотим взять. Это редко на самом деле. И не обязательно, если не поддерживать возможность рекурсивного захвата. Если все плохо — исключение, иначе пушим в стек новый рут и вызываем родной Monitor.Enter. При выходе обязательно проверить что выходим из того рута, который брали последним, выпихиваем его из стека.
Основные накладные расходы в рантайме — чтение [ThreadStatic] и иногда запись в него (один раз на тред). Поддержаны методы Enter/Exit, Wait/Pulse, была когда-то поддержка блокировок, скомбинированными с ReaderWriterLock/Slim; добавлена проверка с помощью using того, что выход из лока произведен тем же тредом, который входил (актуально из-за возможности await внутри using-а async методов).


И теперь вопросы к Sinix.

Re: секунда WTF (lock)
От: fddima  
Дата: 27.01.17 21:16
Оценка: 22 (2) +1
Здравствуйте, samius, Вы писали:

S>* что должно быть напечатано в консоли по теории?

S>* у кого что на практике?
А х.з. что там в теории.
Учитывая что в C# компиляторе очень любят позднее связывание, то твои собственные Enter/Exit должны быть вызваны.
Ну понятно, что если взять код как есть — то только Enter (т.к. enter не устанавливает locked = true).
Re[2]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 07:13
Оценка: 15 (3)
Здравствуйте, fddima, Вы писали:

FF> Учитывая что в C# компиляторе очень любят позднее связывание, то твои собственные Enter/Exit должны быть вызваны.


Для таких вещей рекомендую tryroslyn. Местный класс вызывается, без [mscorlib].
Re[7]: секунда WTF (lock)
От: fddima  
Дата: 28.01.17 15:20
Оценка: 9 (2) +1
Здравствуйте, Sinix, Вы писали:

S>Ну и перехватывать локи, разумеется не через хак с компилятором, а с Fody/PostSharp. И не только Monitor.*, но и спинлоки, wait handles и тыды. Надёжней будет. Собственно, уже.

Я в целом согласен, что PostSharp — более универсальное решение, которое не должно быть подвержено флюктуациям компилятора. Зато потенциально может страдать кучей других проблем связанных с переписыванием кода.

Но и назвать это хаком — не могу. Компилятор ведь не работает с какой-то конкретной версией mscorlib, а то и сам mscorlib компилирует => ему не на что опираться. Я впервые подобное с удивлением обнаружил в Nemerle. Оказывается — повсеместная практика.
Ну и для полноты картины: WellKnownMember-ы.
Re[9]: секунда WTF (lock)
От: fddima  
Дата: 28.01.17 16:20
Оценка: 51 (2)
Здравствуйте, Sinix, Вы писали:

F>> Ну и для полноты картины: WellKnownMember-ы.

S>Там не всё. Expression tree нет, Array.Create (или как там его) нет, Formattable нет, Dictionary нет, String.Concat нет, StructLayout нет. Это первое вспомнившееся.
StructLayoutAttribute — это тип, и он соответственно в WellKnownTypes.
Есть ещё SpecialType и SpecialMember. Вот вокруг них как раз почудить не выйдет.

PS: А Dictionary — зачем там?
Отредактировано 28.01.2017 16:21 Mystic Artifact . Предыдущая версия .
Re[11]: секунда WTF (lock)
От: fddima  
Дата: 28.01.17 16:47
Оценка: 33 (2)
Здравствуйте, Sinix, Вы писали:

F>> PS: А Dictionary — зачем там?

S>http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed
Понял. То ли не знал, то ли забыл... Но рослин так не делает. Вместо этого он считает хэш строки, и генерирует код который сравнивает хэши. Начинает так делать он только если есть как минимум 7 кейсов.

Ну т.е. для:
        public static int Main(string[] args)
        {
            switch (args[0])
            {
                case "s1": return 1;
                case "s2": return 2;
                case "s3": return 3;
                case "s4": return 4;
                case "s5": return 5;
                case "s6": return 6;
                case "s7": return 7;
            }
            return 0;
        }


Он генерирует:

public static int Main(string[] args)
{
    string text = args[0];
    uint num = <PrivateImplementationDetails>.ComputeStringHash(text);
    if (num <= 139573449u)
    {
        if (num != 89240592u)
        {
            if (num != 106018211u)
            {
                if (num == 139573449u)
                {
                    if (text == "s1")
                    {
                        return 1;
                    }
                }
            }
            else if (text == "s3")
            {
                return 3;
            }
        }
        else if (text == "s2")
        {
            return 2;
        }
    }
    else if (num <= 173128687u)
    {
        if (num != 156351068u)
        {
            if (num == 173128687u)
            {
                if (text == "s7")
                {
                    return 7;
                }
            }
        }
        else if (text == "s6")
        {
            return 6;
        }
    }
    else if (num != 189906306u)
    {
        if (num == 206683925u)
        {
            if (text == "s5")
            {
                return 5;
            }
        }
    }
    else if (text == "s4")
    {
        return 4;
    }
    return 0;
}


Где ComputeStringHash:

.method assembly hidebysig static 
    uint32 ComputeStringHash (
        string s
    ) cil managed 
{
    // Method begins at RVA 0x21a8
    // Code size 44 (0x2c)
    .maxstack 2
    .locals init (
        [0] uint32,
        [1] int32
    )

    IL_0000: ldarg.0
    IL_0001: brfalse.s IL_002a

    IL_0003: ldc.i4 -2128831035
    IL_0008: stloc.0
    IL_0009: ldc.i4.0
    IL_000a: stloc.1
    IL_000b: br.s IL_0021
    // loop start (head: IL_0021)
        IL_000d: ldarg.0
        IL_000e: ldloc.1
        IL_000f: callvirt instance char [mscorlib]System.String::get_Chars(int32)
        IL_0014: ldloc.0
        IL_0015: xor
        IL_0016: ldc.i4 16777619
        IL_001b: mul
        IL_001c: stloc.0
        IL_001d: ldloc.1
        IL_001e: ldc.i4.1
        IL_001f: add
        IL_0020: stloc.1

        IL_0021: ldloc.1
        IL_0022: ldarg.0
        IL_0023: callvirt instance int32 [mscorlib]System.String::get_Length()
        IL_0028: blt.s IL_000d
    // end loop

    IL_002a: ldloc.0
    IL_002b: ret
} // end of method '<PrivateImplementationDetails>'::ComputeStringHash


К сожалению ilspy не хочет видеть PrivateImplementationDetails (при декомпиляции в C#).
Отредактировано 28.01.2017 16:48 Mystic Artifact . Предыдущая версия .
[OFF] А какие возможности-то открываются :)
От: fddima  
Дата: 27.01.17 21:31
Оценка: 15 (2)
Здравствуйте, fddima, Вы писали:

Собственно на основе этого можно poor-man's lock logger прикрутить (естественно для текущей сборки).
Хотя я как бы и знал о возможности делать подобные извраты — никогда не делал.

1. Прийдется добавить в файл проекта ручками — студия зачем-то заботливо нас от этого огораживает:
    <Reference Include="mscorlib">
      <Aliases>global,mscorlib</Aliases>
    </Reference>


2.
extern alias mscorlib;
using System;

namespace System.Threading
{
    static class Monitor
    {
        public static void Enter(object obj, ref bool locked)
        {
            Console.WriteLine("Enter");
            mscorlib::System.Threading.Monitor.Enter(obj, ref locked);
        }
        public static void Exit(object obj)
        {
            mscorlib::System.Threading.Monitor.Exit(obj);
            Console.WriteLine("Exit");
        }
    }
}

namespace MonitorEnterTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var syncRoot = new object();
            lock (syncRoot)
            {

            }

            Console.WriteLine("Press any key!!!");
            Console.ReadKey();
        }
    }
}


PS: VS2015U3

UPD: Ну вариант с "happy debug" предложенный практически изначально — я промолчу.
Отредактировано 27.01.2017 21:34 Mystic Artifact . Предыдущая версия . Еще …
Отредактировано 27.01.2017 21:32 Mystic Artifact . Предыдущая версия .
Отредактировано 27.01.2017 21:31 Mystic Artifact . Предыдущая версия .
Re[10]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 16:26
Оценка: 14 (2)
Здравствуйте, fddima, Вы писали:

F> PS: А Dictionary — зачем там?

http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed
Re[6]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 14:33
Оценка: 8 (1) +1
Здравствуйте, samius, Вы писали:


S>>Да ладно? Сначала матчасть, затем на бгоневичнок. Порядок важен

S>Этот инструмент не покажет потенциальный дедлок, а покажет только случившийся и пойманный на машине разработчика. Т.е. когда уже помидоры в смятку.
А, это тоже есть. Было, в смысле. Typemock Racer, CHESS, Jinx — их популярность как бы намекает на актуальность проблемы и эффективность инструментов. Серьёзно, написать корректно сразу — на порядки выгодней, чем надеяться поймать гейзенбаги тестированием.


S>Да, я использую level-ы синкрутов, как по первой ссылке. Но даже при этом контроль времени выполнения при попытке захвата в неверном порядке не помешает. ИМХО. Уже на стадии прогона тестов я знаю что дедлока не будет.

Неа. Ты знаешь, что дедлок не воспроизводится с некоторой вероятностью, не больше того. С учётом того, что дедлоки уже ловились раньше, как ты пишешь — не самая обнадёживающая информация

Вероятность конечно можно повысить — собирать зависимые локи (один lock берётся внутри другого) за всё время выполнения процесса и искать петли в графе зависимостей. К сожалению, это не спасёт от десятков прочих ошибок типа неявного разделяемого состояния, обращения к ресурсу вне локов, использования thread-local-переменных или блокировок вперемешку с async. Выгодней сразу свести разделяемое состояние к минимуму и по минимуму же использовать примитивы синхронизации. Меньше мест, где можно ошибиться — меньше ошибок — профит.

Ну и перехватывать локи, разумеется не через хак с компилятором, а с Fody/PostSharp. И не только Monitor.*, но и спинлоки, wait handles и тыды. Надёжней будет. Собственно, уже.

S>И представь, я не занимаюсь целенаправленным достижением дедлоков, но контроль срабатывает довольно часто.

Ну, бардак в проекте, без обид. Я за 10 лет сталкивался с неожиданными дедлоками ровно два раза. Оба раза товарищ разработчик считал, что большие красные буквы в мануале — это не для него.
Re[7]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 17:28
Оценка: 50 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:



S>>>Да ладно? Сначала матчасть, затем на бгоневичнок. Порядок важен

S>>Этот инструмент не покажет потенциальный дедлок, а покажет только случившийся и пойманный на машине разработчика. Т.е. когда уже помидоры в смятку.
S>А, это тоже есть. Было, в смысле. Typemock Racer, CHESS, Jinx — их популярность как бы намекает на актуальность проблемы и эффективность инструментов. Серьёзно, написать корректно сразу — на порядки выгодней, чем надеяться поймать гейзенбаги тестированием.
А что, сопровождение и развитие уже не в почете?

S>>Да, я использую level-ы синкрутов, как по первой ссылке. Но даже при этом контроль времени выполнения при попытке захвата в неверном порядке не помешает. ИМХО. Уже на стадии прогона тестов я знаю что дедлока не будет.

S>Неа. Ты знаешь, что дедлок не воспроизводится с некоторой вероятностью, не больше того. С учётом того, что дедлоки уже ловились раньше, как ты пишешь — не самая обнадёживающая информация
Разве я написал что они ловились? Нет, я написал что они ловились на этапе тестирования — а значит еще до коммита. Это раз.
Второе — проверка кидает исключение не в тот момент, когда дедлок возникает, а в момент, когда код первый раз проходит по месту, где делается вложенный lock с синкрутом неверного уровня. Т.е. от первого прохода по коду, где потенциально когда-нибудь задедлочит.

S>Вероятность конечно можно повысить — собирать зависимые локи (один lock берётся внутри другого) за всё время выполнения процесса и искать петли в графе зависимостей. К сожалению, это не спасёт от десятков прочих ошибок типа неявного разделяемого состояния, обращения к ресурсу вне локов, использования thread-local-переменных или блокировок вперемешку с async. Выгодней сразу свести разделяемое состояние к минимуму и по минимуму же использовать примитивы синхронизации. Меньше мест, где можно ошибиться — меньше ошибок — профит.

Петли в графе зависимостей убраны с помощью расстановки уровней. Их нет потому что нет. И доказано что весь код берет локи в правильном порядке просто фактом прохода по этому коду в интеграционном тесте.
От блокировок вперемешку с async спасает ключевое слово lock, к которому я и пытаюсь подрулить с помощью недокументированных возможностей. А сейчас мне в этом рантайм проверка помогает.

S>Ну и перехватывать локи, разумеется не через хак с компилятором, а с Fody/PostSharp. И не только Monitor.*, но и спинлоки, wait handles и тыды. Надёжней будет. Собственно, уже.

Еще раз. Проверка уровней ловит первый захват в неверном порядке, саму потенциальную ситуацию. PostSharp ловит дедлок в рантайме (а значит, не создание потенциальной ситуации, он ничего не знает о потенциальных ситуациях, нет маркировки уровней), а при самом дедлоке, непосредственно вместо блокировки. А это с большой вероятностью случится после коммита изменений, а то и вообще в продакшне. Давай все-таки, ты сначала поймешь то, о чем я пишу, потом будешь советовать. Без обид? А то твои советы выглядят поверхностными.

S>>И представь, я не занимаюсь целенаправленным достижением дедлоков, но контроль срабатывает довольно часто.

S>Ну, бардак в проекте, без обид. Я за 10 лет сталкивался с неожиданными дедлоками ровно два раза. Оба раза товарищ разработчик считал, что большие красные буквы в мануале — это не для него.
В тестах контроль срабатывал, в тестах (до коммита еще). Если бы такая штука была у твоего товарища разработчика, то ты бы не увидел и этих дедлоков. Полагаю, что PostSharp у него все же стоит? Нет?

Вообще, чего я оправдываюсь? Я не чувствую что набедокурил.
Re[10]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 18:10
Оценка: 26 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>А сейчас я всобачиваю туда константу LockLevels.Utilities = int.MaxValue;

S>Ну так можно это дело флагом оформить или оставить возможность заполнять вручную. Или как ты написал —
S>

S>назначать уровень исходя из предположения что из под этого лока уже никого не вызовут.

Да, пусть так.

S>>Вообще лучше видеть карту уровней на одном экране, что бы можно было над ней курить, не носясь по исходникам. ИМХО.

S>Не проблема абсолютно. В отладочных сборках добавляем дочерние lockobj в список, который хранится в корневом — профит.
Угу, должно получиться здорово. В лучшем случае за это не будут бить (ногами (больно)). На большее не рассчитываю. То есть, обещать что впишусь в такой проект не стану. Но буду искренне рад, если это кому-то поможет (в любой форме).
Re[9]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 20:12
Оценка: 25 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>А что, сопровождение и развитие уже не в почете?

S>Ну вот не срослось ни у одного из проектов, хотя всей магии там — только инжекция кода в рантайме / при компиляции. Не бог весть какая сложная задача.
Что именно? Сопровождение не срослось?


S>>Разве я написал что они ловились? Нет, я написал что они ловились на этапе тестирования — а значит еще до коммита. Это раз.

S>Да это понятно. Я про фразу "я знаю что дедлока не будет". Чересчур оптимистично как-то
Мой оптимизм с инструментальным контролем проверки уровня немного оптимистичнее твоего без онного.


S>>И доказано что весь код берет локи в правильном порядке просто фактом прохода по этому коду в интеграционном тесте.

S>Не "доказано", а "не поймано", сорри за занудство. Самые частые проблемы — наличие нескольких иерархий локов, неявные блокировки или "ослабленные" иерархии, в которых разрешается пропускать часть локов. И то и другое, и третье поймать не так просто Я про что-то типа такого.
S>
S>        var x = new object();
S>        lock (x)
S>        {
S>            Task.Run(() => { lock (x) { } }).Wait();
S>        }
S>

Хорошо, я не имел в виду все возможные типы блокировок. А PostSharp такую вычислит?

S>>От блокировок вперемешку с async спасает ключевое слово lock, к которому я и пытаюсь подрулить с помощью недокументированных возможностей.

S>Если бы спасало См пример выше.
я про
lock (x)
{
   await Task.Run(...);
}



S>>Еще раз. Проверка уровней ловит первый захват в неверном порядке, саму потенциальную ситуацию. PostSharp ловит дедлок в рантайме

S>Не только фактический дедлок, он хранит граф объектов и проверяет на петли. Там слегка упрощённый анализ емнип, но за основу можно взять
Он выстрелит раньше, чем случатся обстоятельства, ведущие без него к дедлоку?
Так вот, маркировка уровней избавляяет от необходимости этот граф строить и проверять на петли. Единственный контроль, который нужен — что порядок уровней не нарушается при очередном захвате.

S>> (а значит, не создание потенциальной ситуации, он ничего не знает о потенциальных ситуациях, нет маркировки уровней)

S>Маркировка уровней не нужна для обнаружения потенциального дедлока. Достаточно поймать образование петли в графе, узлы которого захватывались разными потоками. Можно запретить reentrancy — тогда даж владение узлов проверять не нужно. Ну и уж точно не нужно требовать одновременности локировок. Просто собирать и достраивать граф за всё время жизни процесса с тестами — отлично рабтает. Я с этой фигнёй игрался лет так 5 назад. Ну да, ошибки ловятся, но на практике толку от этого немного. Заменить блокирующие ожидания на CPS выгоднее получается.
Что бы проверять петли графа — его надо строить (в рантайме), делать проверку на петлю при каждой попытке блокировки, достраивать ребро при удачном захвате, удалять при выходе из лока.
А уровень проверяется одним сравнением целого с целым. Если не считать обращение к [ThreadStatic] полю.

CPS — это continuation-ы? Таски? Не всегда это выгоднее.

S>>Вообще, чего я оправдываюсь? Я не чувствую что набедокурил.

S>В смысле оправдываешься? Мы вроде опытом делимся, а не спорим

А ощущение что меня сейчас накажут если не отверчусь
Re[11]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.01.17 13:28
Оценка: 25 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Что именно? Сопровождение не срослось?

S>Ну да — все проекты, что перечислил выше умерли. Даже опенсорсный CHESS — не нужныи оно никому оказалось.
Ок, понял.


S>>Мой оптимизм с инструментальным контролем проверки уровня немного оптимистичнее твоего без онного.

S>Есть такое дело Точнее, я рассчитываю на то, что если при написании кода нет блокирующих ожиданий и петель, то и о дедлоках заботиться незачем. Ну, а если чего вдруг и проскользнёт — то они обломится на await с timeout-ами и этого будет достаточно для диагностики. Пока что этот подход не подводил, смысла дёргаться не вижу

Конечно незачем если при написании нет блокирующих ожиданий. А вот у меня проект чуть ли не весь из блокирующих ожиданий. А что бы не было петель — контроль.

S>>А уровень проверяется одним сравнением целого с целым. Если не считать обращение к [ThreadStatic] полю.


S>Ну тут всё от доверия к коду зависит. Для произвольного кода только проверки на уровень иерархии лока недостаточно, как по мне.

Хорошо, а чего будет достаточно?

S>>CPS — это continuation-ы? Таски? Не всегда это выгоднее.

S>О, а давай пример тогда Хоть какой. А то у меня пока в основном обратные примеры копятся — без сложных локов проще.
Дык я не спорю что без них проще.
Текущий проект, над которым работаю — сервис, обслуживающий коллбэки из драйвера файловой системы. Типа смарткэша для облачного файлового хранилища (корпоративного, не личного).
Блокировками (в том числе) защищена единая модель дерева файлов в памяти. В следующей версии мне дали добро на переход к модели, построенной по функциональным принципам (на неизменяемых данных), что бы уйти от блокировок при обращении к модели. Но модель дерева файлов — не единственное, что требует блокировок.
Re[12]: секунда WTF (lock)
От: Sinix  
Дата: 29.01.17 14:00
Оценка: 20 (1)
Здравствуйте, samius, Вы писали:

S>>Ну тут всё от доверия к коду зависит. Для произвольного кода только проверки на уровень иерархии лока недостаточно, как по мне.

S>Хорошо, а чего будет достаточно?
Ну как минимум — отслеживание всех блокирующих вызовов (их не так уж и много). Иначе будут неловящиеся дедлоки, пример уже подкидывал. В идеале — ещё и трассировку async-callback-ов добавить, через async local. Но это уже по желанию.



S>Текущий проект, над которым работаю — сервис, обслуживающий коллбэки из драйвера файловой системы. Типа смарткэша для облачного файлового хранилища (корпоративного, не личного).

S>Блокировками (в том числе) защищена единая модель дерева файлов в памяти.

А. Мы такое когда-то делали на очередях и cqrs-style (хотя тогда cqrs ещё в моде вроде не был... что-то подобное короч) уведомлениях об изменении данных. Но у нас не было требования консистентности, т.е. модель в памяти могла отражать содержимое файлов с некоторой задержкой. Ну, и данные делились так, чтобы отдельные части можно было безопасно обновлять параллельно, каждая часть обрабатывалась в один поток. В общем, 9/10 всех костылей было убрано ещё в момент проектирования и работать было сплошным удовольствием.

Если требование консистентности есть — то да, жизнь становится заметно интереснее
Отредактировано 29.01.2017 14:01 Sinix . Предыдущая версия .
Re[7]: секунда WTF (lock)
От: Sinix  
Дата: 30.01.17 12:13
Оценка: 20 (1)
Здравствуйте, samius, Вы писали:

S>>Вся разница — надёжней и больше сценариев покрывается.

S>За счет чего более полное-то? Просто убирается хак и только лишь.

За счёт того, что покрываются RW lock, Thread.Join, Semaphore.WaitOne() и прочие примитивы синхронизации.


S>>В смысле не принудительно? Подключил библиотеку — получи тип System.Threading.Monitor в подарок. Или мы уже какое-то другое решение обсуждаем?

S>Подключил — получи Monitor — абсолютно не вариант.
Ну я про это же говорю. Отдельной библиотекой — почему бы и нет?


S>Не, тут либо я что-то не понял, либо теряется часть сценариев. Не нужно требовать что бы перед локом таким-то обязательно был взят такой-то. Это более сильное требование, чем необходимо. Если можно взять b после a, то можно взять b и без a, но если взял b — не бери a. Это делает родителей необязательными.

Не, ссылка на родителя — только чтобы автоматом получать уровень блокировки, не прописывая циферки ручками. Остальное как у тебя.
Re: [OFF] А какие возможности-то открываются :)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 04:16
Оценка: 16 (1)
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, fddima, Вы писали:


F>Собственно на основе этого можно poor-man's lock logger прикрутить (естественно для текущей сборки).

F>Хотя я как бы и знал о возможности делать подобные извраты — никогда не делал.

F>1. Прийдется добавить в файл проекта ручками — студия зачем-то заботливо нас от этого огораживает:

F>
F>    <Reference Include="mscorlib">
F>      <Aliases>global,mscorlib</Aliases>
F>    </Reference>
F>


F>2.

F>[c#]
F>extern alias mscorlib;
F>using System;

F>namespace System.Threading

F>{
F> static class Monitor
F> {
F> public static void Enter(object obj, ref bool locked)
F> {
F> Console.WriteLine("Enter");
F> mscorlib::System.Threading.Monitor.Enter(obj, ref locked);
F> }
F> public static void Exit(object obj)
F> {
F> mscorlib::System.Threading.Monitor.Exit(obj);
F> Console.WriteLine("Exit");
F> }
F> }
F>}
Да, именно так и предполагалось использовать, только не для логов, а для рантайм проверки возможности дедлоков. (и даже больше, доказывания отсутствия возможности таковых при очередном захвате).
Из-за нестабильности эффекта вместо lock-а пришлось перейти на using, и все было ничего, пока компилятор не разрешил внутрь using-а вставлять await-ы. Теперь пришлось доказывать еще что из using-а выходит именно тот поток, что входил.

F>PS: VS2015U3

Аналогично

F>UPD: Ну вариант с "happy debug" предложенный практически изначально — я промолчу.

В заглавном сообщении меня интересовал именно факт вызова моих методов из под штатного lock-а. Понятно что без mscorlib или своего аналога это злая засада.
Re[12]: секунда WTF (lock)
От: rameel https://github.com/rsdn/CodeJam
Дата: 28.01.17 17:31
Оценка: 16 (1)
Здравствуйте, fddima, Вы писали:

F>К сожалению ilspy не хочет видеть PrivateImplementationDetails (при декомпиляции в C#).


ComputeStringHash
/// <summary>
/// Compute the hashcode of a sub string using FNV-1a
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
/// </summary>
/// <remarks>
/// This method should be kept consistent with MethodBodySynthesizer.ConstructStringSwitchHashFunctionBody
/// The control flow in this method mimics lowered "for" loop. It is exactly what we want to emit
/// to ensure that JIT can do range check hoisting.
/// </remarks>
internal static uint ComputeStringHash(string text)
{
    uint hashCode = 0;
    if (text != null)
    {
        hashCode = unchecked((uint)2166136261);

        int i = 0;
        goto start;

    again:
        hashCode = unchecked((text[i] ^ hashCode) * 16777619);
        i = i + 1;

    start:
        if (i < text.Length)
            goto again;
    }
    return hashCode;
}
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[5]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 09:01
Оценка: 8 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>>Как по мне, это не WTF, а instant karma: использовал недокументированное поведение — вот тебе недокументированное поведение

S>>Я не от хорошей жизни и нечего делать такое пытаюсь использовать. А от того, что у lock-а нет никаких инструментов для того что бы не наступить на помидоры. Скоро уж 20 лет как.

S>Да ладно? Сначала матчасть, затем на бгоневичнок. Порядок важен

Этот инструмент не покажет потенциальный дедлок, а покажет только случившийся и пойманный на машине разработчика. Т.е. когда уже помидоры в смятку.

S>Другое дело, что никакие инструменты не спасут, если целенаправленно пишется код, потенциально приводящий к дедлокам. Надо подход менять. В идеале — cps-style на await, на крайний случай — чужой опыт хождения по граблям.

Да, я использую level-ы синкрутов, как по первой ссылке. Но даже при этом контроль времени выполнения при попытке захвата в неверном порядке не помешает. ИМХО. Уже на стадии прогона тестов я знаю что дедлока не будет.
И представь, я не занимаюсь целенаправленным достижением дедлоков, но контроль срабатывает довольно часто.
Re[11]: секунда WTF (lock)
От: Sharov Россия  
Дата: 30.01.17 11:51
Оценка: 2 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Что именно? Сопровождение не срослось?

S>Ну да — все проекты, что перечислил выше умерли. Даже опенсорсный CHESS — не нужныи оно никому оказалось.

Потому что для серьезных продуктов инструмент уже придуман -- https://en.wikipedia.org/wiki/TLA%2B#Industry_use (TLA+).
Отсутствие спроса на подобные инструменты/анализаторы для дотнет говорит не в пользу платформы.
Кодом людям нужно помогать!
Re[2]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 07:07
Оценка: +1
Здравствуйте, samius, Вы писали:

S>http://ideone.com/tR2ntD


S>Не заходит в мой Enter

Потому что mono compiler. Стандартный enter вызывается.

Как по мне, это не WTF, а instant karma: использовал недокументированное поведение — вот тебе недокументированное поведение
Re[8]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 15:36
Оценка: +1
Здравствуйте, fddima, Вы писали:

F> Я в целом согласен, что PostSharp — более универсальное решение, которое не должно быть подвержено флюктуациям компилятора. Зато потенциально может страдать кучей других проблем связанных с переписыванием кода.


Ну так чисто для тестирования, в продакшн такое выпускать — мазохистов нет


F> Но и назвать это хаком — не могу.

Именно что хак, контракт не зафиксирован и меняется от редакции к редакции. В отличие от linq, AsyncTaskMethodBuilder или .GetEnumerator().


F> Ну и для полноты картины: WellKnownMember-ы.

Там не всё. Expression tree нет, Array.Create (или как там его) нет, Formattable нет, Dictionary нет, String.Concat нет, StructLayout нет. Это первое вспомнившееся.
Re[2]: секунда WTF (lock)
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 28.01.17 19:38
Оценка: +1
Здравствуйте, romangr, Вы писали:

R>А вообще кто-нибудь знает, зачем сделали возможность делать lock на произвольном объекте?

R>Сделали бы только Monitor и все только с его экземплярами?

Содрали с жабы не включая моск.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[13]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.01.17 15:29
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Хорошо, а чего будет достаточно?

S>Ну как минимум — отслеживание всех блокирующих вызовов (их не так уж и много). Иначе будут неловящиеся дедлоки, пример уже подкидывал. В идеале — ещё и трассировку async-callback-ов добавить, через async local. Но это уже по желанию.
Да, при обращении к блокирующим асинхронным вызовам (например, сервера) могу потребовать отсутствия захватов у вызывающего потока, раз я их (захваты) отслеживаю.
Хорошая мысль, спасибо. Хоть это требование должно быть не забыто добавлено в код руками, оно просигналит что блокирующий код вызван из под lock-а.


S>>Текущий проект, над которым работаю — сервис, обслуживающий коллбэки из драйвера файловой системы. Типа смарткэша для облачного файлового хранилища (корпоративного, не личного).

S>>Блокировками (в том числе) защищена единая модель дерева файлов в памяти.

S>А. Мы такое когда-то делали на очередях и cqrs-style (хотя тогда cqrs ещё в моде вроде не был... что-то подобное короч) уведомлениях об изменении данных. Но у нас не было требования консистентности, т.е. модель в памяти могла отражать содержимое файлов с некоторой задержкой. Ну, и данные делились так, чтобы отдельные части можно было безопасно обновлять параллельно, каждая часть обрабатывалась в один поток. В общем, 9/10 всех костылей было убрано ещё в момент проектирования и работать было сплошным удовольствием.


S>Если требование консистентности есть — то да, жизнь становится заметно интереснее

Хм, навскидку сложно сказать, может ли драйвер файловой системы теоретически работать с cqrs, все-таки какие-то гарантии требует и сам Windows при обращении к драйверу. Создание файла подразумевает возврат хэндла созданного файла, что вроде бы уже выпадает из cqrs. Можно ли там схитрить — фиг знает.
секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.01.17 20:02
Оценка:
Всем привет. Думаю, что на минутку не тянет, потому секунда.

namespace System.Threading
{
    static class Monitor
    {
        public static void Enter(object obj, ref bool locked)
        {
            Console.WriteLine("Enter");
        }
        public static void Exit(object obj)
        {
            Console.WriteLine("Exit");
        }
    }
}

namespace MonitorEnterTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var syncRoot = new object();
            lock (syncRoot)
            {

            }

            Console.WriteLine("Press any key!!!");
            Console.ReadKey();
        }
    }
}


Вопросы:
* что должно быть напечатано в консоли по теории?
* у кого что на практике?

З.Ы. на моей машине и на ideone результаты отличаются. Я бы не писал, если бы результат был стабилен и совпадал с аналогичным много лет назад (может быть около 10и) с поправкой на изменившуюся сигнатуру Enter(object, bool&).

З.Ы.2 Правильные ответы не знаю.
Отредактировано 30.01.2017 18:40 AndrewVK . Предыдущая версия .
async
Re: секунда WTF (lock)
От: Слава  
Дата: 27.01.17 21:01
Оценка:
Здравствуйте, samius, Вы писали:

S>Всем привет. Думаю, что на минутку не тянет, потому секунда.


S>З.Ы.2 Правильные ответы не знаю.


А где вызовы-то?
Re[2]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 04:01
Оценка:
Здравствуйте, Слава, Вы писали:

С>Здравствуйте, samius, Вы писали:


С>А где вызовы-то?

Вызовы подставляет компилятор
Re[2]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 04:03
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, samius, Вы писали:


S>>* что должно быть напечатано в консоли по теории?

S>>* у кого что на практике?
F> А х.з. что там в теории.
F> Учитывая что в C# компиляторе очень любят позднее связывание, то твои собственные Enter/Exit должны быть вызваны.
Да, была на это надежда. Но ideone не пишет даже "Enter"

F> Ну понятно, что если взять код как есть — то только Enter (т.к. enter не устанавливает locked = true).

Ох, забыл я ночью его повернуть-то. Да, с ним теперь и "Exit" увидел. Благодарю.
Re: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 04:24
Оценка:
Здравствуйте, samius, Вы писали:

S>З.Ы. на моей машине и на ideone результаты отличаются.


http://ideone.com/tR2ntD

Не заходит в мой Enter
Re[3]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 08:15
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>http://ideone.com/tR2ntD


S>>Не заходит в мой Enter

S>Потому что mono compiler. Стандартный enter вызывается.

S>Как по мне, это не WTF, а instant karma: использовал недокументированное поведение — вот тебе недокументированное поведение

Я не от хорошей жизни и нечего делать такое пытаюсь использовать. А от того, что у lock-а нет никаких инструментов для того что бы не наступить на помидоры. Скоро уж 20 лет как.
Re[4]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 08:47
Оценка:
Здравствуйте, samius, Вы писали:

S>>Как по мне, это не WTF, а instant karma: использовал недокументированное поведение — вот тебе недокументированное поведение

S>Я не от хорошей жизни и нечего делать такое пытаюсь использовать. А от того, что у lock-а нет никаких инструментов для того что бы не наступить на помидоры. Скоро уж 20 лет как.

Да ладно? Сначала матчасть, затем на бгоневичнок. Порядок важен

Другое дело, что никакие инструменты не спасут, если целенаправленно пишется код, потенциально приводящий к дедлокам. Надо подход менять. В идеале — cps-style на await, на крайний случай — чужой опыт хождения по граблям.
Re[3]: секунда WTF (lock)
От: Слава  
Дата: 28.01.17 09:35
Оценка:
Здравствуйте, samius, Вы писали:

С>>А где вызовы-то?

S>Вызовы подставляет компилятор

Как-то это не гарантировано.
Re[3]: секунда WTF (lock)
От: fddima  
Дата: 28.01.17 14:26
Оценка:
Здравствуйте, samius, Вы писали:

F>> Учитывая что в C# компиляторе очень любят позднее связывание, то твои собственные Enter/Exit должны быть вызваны.

S>Да, была на это надежда. Но ideone не пишет даже "Enter"
На ideone — mono небось? Если так — то, имхо, это косяк в mcs и ориентироваться следует на рослин.
Re[8]: секунда WTF (lock)
От: Sinix  
Дата: 28.01.17 19:05
Оценка:
Здравствуйте, samius, Вы писали:

S>А что, сопровождение и развитие уже не в почете?

Ну вот не срослось ни у одного из проектов, хотя всей магии там — только инжекция кода в рантайме / при компиляции. Не бог весть какая сложная задача.


S>Разве я написал что они ловились? Нет, я написал что они ловились на этапе тестирования — а значит еще до коммита. Это раз.

Да это понятно. Я про фразу "я знаю что дедлока не будет". Чересчур оптимистично как-то


S>И доказано что весь код берет локи в правильном порядке просто фактом прохода по этому коду в интеграционном тесте.

Не "доказано", а "не поймано", сорри за занудство. Самые частые проблемы — наличие нескольких иерархий локов, неявные блокировки или "ослабленные" иерархии, в которых разрешается пропускать часть локов. И то и другое, и третье поймать не так просто Я про что-то типа такого.
        var x = new object();
        lock (x)
        {
            Task.Run(() => { lock (x) { } }).Wait();
        }


S>От блокировок вперемешку с async спасает ключевое слово lock, к которому я и пытаюсь подрулить с помощью недокументированных возможностей.

Если бы спасало См пример выше.


S>Еще раз. Проверка уровней ловит первый захват в неверном порядке, саму потенциальную ситуацию. PostSharp ловит дедлок в рантайме

Не только фактический дедлок, он хранит граф объектов и проверяет на петли. Там слегка упрощённый анализ емнип, но за основу можно взять

S> (а значит, не создание потенциальной ситуации, он ничего не знает о потенциальных ситуациях, нет маркировки уровней)

Маркировка уровней не нужна для обнаружения потенциального дедлока. Достаточно поймать образование петли в графе, узлы которого захватывались разными потоками. Можно запретить reentrancy — тогда даж владение узлов проверять не нужно. Ну и уж точно не нужно требовать одновременности локировок. Просто собирать и достраивать граф за всё время жизни процесса с тестами — отлично рабтает. Я с этой фигнёй игрался лет так 5 назад. Ну да, ошибки ловятся, но на практике толку от этого немного. Заменить блокирующие ожидания на CPS выгоднее получается.


S>Вообще, чего я оправдываюсь? Я не чувствую что набедокурил.

В смысле оправдываешься? Мы вроде опытом делимся, а не спорим
Re: секунда WTF (lock)
От: romangr Россия  
Дата: 28.01.17 19:36
Оценка:
Здравствуйте, samius, Вы писали:
S>З.Ы.2 Правильные ответы не знаю.

А вообще кто-нибудь знает, зачем сделали возможность делать lock на произвольном объекте?
Сделали бы только Monitor и все только с его экземплярами?
... << RSDN@Home (RF) 1.2.0 alpha 5 rev. 67>>
Re[8]: секунда WTF (lock)
От: Слава  
Дата: 28.01.17 20:03
Оценка:
Здравствуйте, samius, Вы писали:

S>Вообще, чего я оправдываюсь? Я не чувствую что набедокурил.


А есть ли у вас возможность просто собирать дампы на клиенте? Ну чтобы если лок висит больше какого-то разумного времени, то убивать процесс целиком и снимать дамп с помощью Windows Error Reporting
Re[9]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.01.17 20:24
Оценка:
Здравствуйте, Слава, Вы писали:

С>Здравствуйте, samius, Вы писали:


S>>Вообще, чего я оправдываюсь? Я не чувствую что набедокурил.


С>А есть ли у вас возможность просто собирать дампы на клиенте? Ну чтобы если лок висит больше какого-то разумного времени, то убивать процесс целиком и снимать дамп с помощью Windows Error Reporting

Нету такой возможности.
Re[10]: секунда WTF (lock)
От: Sinix  
Дата: 29.01.17 10:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Что именно? Сопровождение не срослось?

Ну да — все проекты, что перечислил выше умерли. Даже опенсорсный CHESS — не нужныи оно никому оказалось.


S>Мой оптимизм с инструментальным контролем проверки уровня немного оптимистичнее твоего без онного.

Есть такое дело Точнее, я рассчитываю на то, что если при написании кода нет блокирующих ожиданий и петель, то и о дедлоках заботиться незачем. Ну, а если чего вдруг и проскользнёт — то они обломится на await с timeout-ами и этого будет достаточно для диагностики. Пока что этот подход не подводил, смысла дёргаться не вижу



S>Что бы проверять петли графа — его надо строить (в рантайме), делать проверку на петлю при каждой попытке блокировки, достраивать ребро при удачном захвате, удалять при выходе из лока.

S>А уровень проверяется одним сравнением целого с целым. Если не считать обращение к [ThreadStatic] полю.

Ну тут всё от доверия к коду зависит. Для произвольного кода только проверки на уровень иерархии лока недостаточно, как по мне.


S>CPS — это continuation-ы? Таски? Не всегда это выгоднее.

О, а давай пример тогда Хоть какой. А то у меня пока в основном обратные примеры копятся — без сложных локов проще.


S>А ощущение что меня сейчас накажут если не отверчусь

Упс
Re: секунда WTF (lock)
От: fddima  
Дата: 29.01.17 23:06
Оценка:
Здравствуйте, samius, Вы писали:

Возможно ли такое, что ты сврй подход щаоаенсорсишь и сделаешь нормальное объяснение как этим пользоваться?
Смотри — первый бенефит — оно нафиг никому не надо.
Второй бенефит — ты потратишь время впустую.

Механизм используемый тобой слишком слоден доя новичков имхо, но, имхо, на самом деле — твоя практика тут... бесценна. Ты ж ведь из тех кто юзает дотнет почти сгачала если я не ошибаюсь, а вае "знакомство" с Sinix волей судеб случилось токс щас? Хотя это дико — я давно ставлб оценки тока ему и рслн меня режет за межуусобничество — но я его в глаза не знаю...
А и пофиг. Мне всегда на них было пофиг.
Просто если есть реально хорошмй опыт — имхо — его стоит описать, тем более если есть примеры.
Безусловно — нужно твоё желание, нужно вообще видение этого как статьи. Я лично доя себя понял что вы межлу собой поговорили о чем-то. Не то. Ну не то что-бы у мну фантазия не работала, но это другое.
@samius, если ты готов поделиться опытом — я думаю как минимум это оценят даже "смежники", вдобавок задача что ты озвучил — два раза как выбивается в интересные — она ведь из области того запрещённого кода где некоторые считаю что никто кроме... (неважне чего — важен факт).
Мне кажется если иы осилишь аггрегировать свой опыт — это было бы интересно.
Нафуя? Х.з.
Re[3]: секунда WTF (lock)
От: Sinix  
Дата: 30.01.17 10:46
Оценка:
Здравствуйте, samius, Вы писали:

S>И теперь вопросы к Sinix.

Их лучше мне в ответе задавать Этот пост чисто случайно прочитал.


S>Вот в таком контексте насколько комильфо в неком сфероконическом случае заюзать недокументированне возможности что бы присесть на lock конструкцию?


Ну... я бы даже заморачиваться не стал рассуждениями комильфо-не комильфо. Такой подход не покрывает часть сценариев (wait handle/spinwait/rwlock/blocking collections etc) => надо использовать что-то другое и не тратить время на полурабочий вариант. Я бы использовал инструментирование кода ч/з Fody, т.к. он бесплатен в отличие от того же постшарпа.



S>Нужна ли такая кухня в CodeJam? Я уже предлагал как-то, но боюсь, что был крайне немногословен. Повторюсь, в каждом проекте оно не нужно. Но и в CodeJam уже дофига экзотики.


Как отдельный проект — безусловно интересно
Как часть библиотеки — чой-то я боюсь пользователи нас не поймут. Реакция "подменять всем lock? вы там совсем упоролись?!!" самая мягкая будет.

Хотя... можно добавить в библиотеку класс LockKey c возможностью в конструкторе задавать ссылку на parent и дальше инструментированием кода отслеживать порядок приобретения локов. Но инструментирование должно быть opt-in, понятное дело.
Re[4]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 11:11
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>И теперь вопросы к Sinix.

S>Их лучше мне в ответе задавать Этот пост чисто случайно прочитал.
Учту


S>>Вот в таком контексте насколько комильфо в неком сфероконическом случае заюзать недокументированне возможности что бы присесть на lock конструкцию?


S>Ну... я бы даже заморачиваться не стал рассуждениями комильфо-не комильфо. Такой подход не покрывает часть сценариев (wait handle/spinwait/rwlock/blocking collections etc) => надо использовать что-то другое и не тратить время на полурабочий вариант. Я бы использовал инструментирование кода ч/з Fody, т.к. он бесплатен в отличие от того же постшарпа.

С rwlock-ами все работало, но это не отменяет что сценариев лишь часть.
Fody — другой уровень решения проблемы. При наличии анализа либо доступа к тому же IL во время компиляции (или исходникам) — лучше анализировать код, а не делать проверки в рантайме. Но опять таки, либо более-менее полное решение, либо смысла в нем не дофига.

S>>Нужна ли такая кухня в CodeJam? Я уже предлагал как-то, но боюсь, что был крайне немногословен. Повторюсь, в каждом проекте оно не нужно. Но и в CodeJam уже дофига экзотики.


S>Как отдельный проект — безусловно интересно

С претензией на полное покрытие сценариев? Очень сомневаюсь по поводу своего участия. Но и возражать против реализации такого проекта не стану.

S>Как часть библиотеки — чой-то я боюсь пользователи нас не поймут. Реакция "подменять всем lock? вы там совсем упоролись?!!" самая мягкая будет.

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

S>Хотя... можно добавить в библиотеку класс LockKey c возможностью в конструкторе задавать ссылку на parent и дальше инструментированием кода отслеживать порядок приобретения локов. Но инструментирование должно быть opt-in, понятное дело.

Что бы ссылку на parent задавать, надо его либо хранить в тредконтексте (тогда зачем задавать явно?), либо тащить по стеку.
Re[5]: секунда WTF (lock)
От: Sinix  
Дата: 30.01.17 11:36
Оценка:
Здравствуйте, samius, Вы писали:

S>Fody — другой уровень решения проблемы. При наличии анализа либо доступа к тому же IL во время компиляции (или исходникам) — лучше анализировать код, а не делать проверки в рантайме. Но опять таки, либо более-менее полное решение, либо смысла в нем не дофига.


Не, это перебор уже, кмк. Fody нужен только чтоб добавить вызовы LockTracer.LockTaken(lockObj) / LockTracer.LockReleased(lockObj) (имена условные) к всем блокировкам, остальное не будет ничем отличаться от текущего варианта с перехватом через "хак" компилятора. Вся разница — надёжней и больше сценариев покрывается.

Про анализ il кода — сами топите урановые ломы в кипящей ртути


S>>Как отдельный проект — безусловно интересно

S>С претензией на полное покрытие сценариев? Очень сомневаюсь по поводу своего участия. Но и возражать против реализации такого проекта не стану.
Ну... тут уж как пойдёт. Даж неполное будет лучше, чем ничего.


S>>Как часть библиотеки — чой-то я боюсь пользователи нас не поймут. Реакция "подменять всем lock? вы там совсем упоролись?!!" самая мягкая будет.

S>Это же не принудительно.
В смысле не принудительно? Подключил библиотеку — получи тип System.Threading.Monitor в подарок. Или мы уже какое-то другое решение обсуждаем?


S>>Хотя... можно добавить в библиотеку класс LockKey c возможностью в конструкторе задавать ссылку на parent и дальше инструментированием кода отслеживать порядок приобретения локов. Но инструментирование должно быть opt-in, понятное дело.

S>Что бы ссылку на parent задавать, надо его либо хранить в тредконтексте (тогда зачем задавать явно?), либо тащить по стеку.
Не, задавать в момент создания, аля
pulic static readonly LockKey RootLockKey = new LockKey("Root");
pulic static readonly LockKey L2LockKey = new LockKey(RootLockKey, "L2");
Re[6]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 12:03
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>Не, это перебор уже, кмк. Fody нужен только чтоб добавить вызовы LockTracer.LockTaken(lockObj) / LockTracer.LockReleased(lockObj) (имена условные) к всем блокировкам, остальное не будет ничем отличаться от текущего варианта с перехватом через "хак" компилятора. Вся разница — надёжней и больше сценариев покрывается.

За счет чего более полное-то? Просто убирается хак и только лишь.

S>Про анализ il кода — сами топите урановые ломы в кипящей ртути

Ненуачо, я не подразумевал себя, чисто как идею.


S>>>Как отдельный проект — безусловно интересно

S>>С претензией на полное покрытие сценариев? Очень сомневаюсь по поводу своего участия. Но и возражать против реализации такого проекта не стану.
S>Ну... тут уж как пойдёт. Даж неполное будет лучше, чем ничего.
И для кого-нибудь — лучше, чем ни для кого. Не, я стал большой, старый и ленивый. Для себя я еще могу напрячься, когда это сэкономит в перспективе. Для других — не жалко, но что бы пахать...


S>>>Как часть библиотеки — чой-то я боюсь пользователи нас не поймут. Реакция "подменять всем lock? вы там совсем упоролись?!!" самая мягкая будет.

S>>Это же не принудительно.
S>В смысле не принудительно? Подключил библиотеку — получи тип System.Threading.Monitor в подарок. Или мы уже какое-то другое решение обсуждаем?
Подключил — получи Monitor — абсолютно не вариант. Я такое не предлагал. Я спросил про хак, и отдельным вопросом — надо ли вообще такой инструмент. А уж если надо, то можно было бы обсудить форму и подачу. Но без принудиловки. Т.е. если это бы был хак, то только путем того что пользователь собственной рукой вставляет в свой проект Monitor, но не подключил — получи.

S>>>Хотя... можно добавить в библиотеку класс LockKey c возможностью в конструкторе задавать ссылку на parent и дальше инструментированием кода отслеживать порядок приобретения локов. Но инструментирование должно быть opt-in, понятное дело.

S>>Что бы ссылку на parent задавать, надо его либо хранить в тредконтексте (тогда зачем задавать явно?), либо тащить по стеку.
S>Не, задавать в момент создания, аля
S>
S>pulic static readonly LockKey RootLockKey = new LockKey("Root");
S>pulic static readonly LockKey L2LockKey = new LockKey(RootLockKey, "L2");
S>

Не, тут либо я что-то не понял, либо теряется часть сценариев. Не нужно требовать что бы перед локом таким-то обязательно был взят такой-то. Это более сильное требование, чем необходимо. Если можно взять b после a, то можно взять b и без a, но если взял b — не бери a. Это делает родителей необязательными.
Re[8]: секунда WTF (lock)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.01.17 12:33
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>За счет чего более полное-то? Просто убирается хак и только лишь.


S>За счёт того, что покрываются RW lock, Thread.Join, Semaphore.WaitOne() и прочие примитивы синхронизации.

Теперь понял.


S>>>В смысле не принудительно? Подключил библиотеку — получи тип System.Threading.Monitor в подарок. Или мы уже какое-то другое решение обсуждаем?

S>>Подключил — получи Monitor — абсолютно не вариант.
S>Ну я про это же говорю. Отдельной библиотекой — почему бы и нет?
смысл в отдельной пропадает, если не хакать lock. Да в общем, если охват будет более полный, то можно и отдельной.


S>>Не, тут либо я что-то не понял, либо теряется часть сценариев. Не нужно требовать что бы перед локом таким-то обязательно был взят такой-то. Это более сильное требование, чем необходимо. Если можно взять b после a, то можно взять b и без a, но если взял b — не бери a. Это делает родителей необязательными.

S>Не, ссылка на родителя — только чтобы автоматом получать уровень блокировки, не прописывая циферки ручками. Остальное как у тебя.
Т.е. ссылка на родителя — разметка для инструмента, который уровни вычислит по меткам и подставит сам? Идея нравится, но не до конца.

Допустим, есть некая утилита, защищенная отдельным локом (сегодня). И этот отдельный лок не нуждается ни в каком контроле, т.к. мы уверены что из кода этой утилиты любой другой код не вызывается, она закончена. Завтра чел в нее добавляет виртуальный метод, объявляет наследника, добавляет фабрику. Послезавтра один из наследников начинает вызывать код бизнес-уровня. Именно поэтому контроль лока для этой утилиты нужен сегодня. Но какого родителя ему указать, какого из, если сегодня он может вызываться из 10и разных мест кода? А сейчас я всобачиваю туда константу LockLevels.Utilities = int.MaxValue;
Можно и не указывать родителя, тогда назначать уровень исходя из предположения что из под этого лока уже никого не вызовут.
Вообще лучше видеть карту уровней на одном экране, что бы можно было над ней курить, не носясь по исходникам. ИМХО.
Re[9]: секунда WTF (lock)
От: Sinix  
Дата: 30.01.17 12:57
Оценка:
Здравствуйте, samius, Вы писали:

S>Т.е. ссылка на родителя — разметка для инструмента, который уровни вычислит по меткам и подставит сам? Идея нравится, но не до конца.

Угу.

S>А сейчас я всобачиваю туда константу LockLevels.Utilities = int.MaxValue;

Ну так можно это дело флагом оформить или оставить возможность заполнять вручную. Или как ты написал —

назначать уровень исходя из предположения что из под этого лока уже никого не вызовут.


S>Вообще лучше видеть карту уровней на одном экране, что бы можно было над ней курить, не носясь по исходникам. ИМХО.

Не проблема абсолютно. В отладочных сборках добавляем дочерние lockobj в список, который хранится в корневом — профит.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.