Re[7]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.13 14:33
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Если желание и понимание есть то сделать можно. Если понимания нет то проблемы с юзингом можно получить и без abort-а. Элементарный случай — исключение в конструкторе.

Можно подробнее?
Re[8]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 14:37
Оценка: -1 :)
Здравствуйте, samius, Вы писали:

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


Tom>>Если желание и понимание есть то сделать можно. Если понимания нет то проблемы с юзингом можно получить и без abort-а. Элементарный случай — исключение в конструкторе.

S>Можно подробнее?
А что подробнее то?
Вот минимальный пример.

namespace ConsoleApplication1
{
    public class Foo : IDisposable
    {
        public Foo()
        {
            // Imagine we have got resource here...
            // And then calling something else
            throw new Exception("вай беда бедаё");
        }
        public void Dispose()
        {
            Console.WriteLine("Disposed");
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (new Foo())
                {

                }
            }
            catch (Exception)
            {
                Console.WriteLine("catched");
            }
        }
    }
}
Народная мудрось
всем все никому ничего(с).
Re[7]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.13 14:38
Оценка: +3
Здравствуйте, Tom, Вы писали:

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


S>>

S>>In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.

Tom>Вы будете удивлены но я абсолютно с ним согласен. Что абсолютно не значит что ThreadAbort зло во всех случаях.
Tom>Есть целый класс случаев когда без него просто невозможно обойтись.
А он и не пишет что зло во всех случаях. Он пишет "избегать любой ценой".
Tom>Это случаи когда вы не владеете кодом который выполняется в вашем потоке в данную минуту.
Для меня это = практически всегда. Даже из файла прочитать не можем, не выполняя код, которым не владеем.
Tom>Примеры ASP.NET, WCF, SQL Server & CLR.
Tom>Во всех этих примерах применяется ThreadAbort
Да, я видел что в ASP.NET чуть ли не принято было звать Abort чуть ли не в каждом запросе. Я не одобряю эту практику.
Re[9]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.13 14:39
Оценка: +1
Здравствуйте, Tom, Вы писали:

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


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


Tom>>>Если желание и понимание есть то сделать можно. Если понимания нет то проблемы с юзингом можно получить и без abort-а. Элементарный случай — исключение в конструкторе.

S>>Можно подробнее?
Tom>А что подробнее то?
Tom>Вот минимальный пример.

Пардон, я не вижу в этом примере проблемы с юзингом. Я вижу проблему с пониманием конструкции юзинг.
Re[3]: ReaderWriterLockSlim problems
От: MozgC США http://nightcoder.livejournal.com
Дата: 16.12.13 16:21
Оценка: +5
Tom, если вкратце, то я понимаю, что в некоторых ситуациях может показаться, что Thread.Abort использовать можно. Да и вам лично никто не запретит Проблема в том, что гарантировать, что поток не использует каких-то разделяемых ресурсов, и что Thread.Abort() в таком случае не приведет к проблеме, очень проблематично. Вы будете проверять внутренности всех методов вызываемых потоком? Что они там внутри делают, не используется ли там внутри разделяемое состояние? Есть ли гарантии что программист при этом не ошибётся? Поэтому просто как rule of thumb считается, что Thread.Abort() использовать не нужно никогда. При этом да, при желании (или из принципа, чтобы доказать ) вы можете написать метод потока, который можно завершить с Thread.Abort() и ничего супер страшного не произойдет.
Re[7]: ReaderWriterLockSlim problems
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 16.12.13 18:06
Оценка: 159 (8)
Здравствуйте, Tom, Вы писали:

Ок, давай сделаем небольшую перезагрузку

Рассмотрим такой код:

public sealed class ResourceWrapper : IDisposable
{
    private readonly HandleWrapper _wrapper;
    public ResourceWrapper()
    {
        _wrapper = new HandleWrapper {Handle = AcquireHandle()};
    }

    ~ResourceWrapper()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        // Финализатор может быть вызван для неполностью 
        // сконструированного объекта!!
        if (_wrapper.Handle != IntPtr.Zero)
        {
            ReleaseHandle(_wrapper.Handle);
        }
    }


    private static IntPtr AcquireHandle()
    {
        return IntPtr.Zero;
    }

    private static void ReleaseHandle(IntPtr handle)
    {
        // Do something to release handle!
    }
    struct HandleWrapper
    {
        public IntPtr Handle;
    } 
}


Давай внимательно на него посмотрим и ответим на вопрос, является ли класс ResourceWrapper безопасным с точки зрения исключений?
Да, есть три гарантии безопасности исключений по Абрамсу: базовая, строгая и гарантия отсутствия исключений.

С первого взгляда кажется, что этот класс обеспечивает базовую гарантию исключений и утечки ресурсов здесь невозможны. И это действительно так и есть, если говорить об обычных исключениях. Но в CLR (и в CLI) помимо синхронных, есть еще несколько специальных асинхронных исключений, которые могут быть сгенерированы CLR практически в любой точке программы. К таким исключениям относятся: StackOverflowException, OutOfMemoryException и ThreadAbortException.

Теперь, если посмотреть, что я не стал создавать конструктор для вложенной структуры HandleWrapper, то станет понятно, что против асинхронных исключений, данный код не является безопасным!

Поскольку ThreadAbortException может возникнуть практически в любой точке приложения, кроме блока finally, unmanaged коде и Critical Excecution Region-ах, то без изменений, данный код будет небезопасным.

Безопасность исключений, это как и безопасность вообще, если есть хотя бы один небезопасный класс, то и все классы, которые его используют становятся небезопасными с точки зрения исключений. Поэтому если я предоставлю в качестве библиотеки класс ResourceWrapper, хорошо проверенный и протестированный, то все ваше приложение будет небезопасным с точки зрения асинхронных исключений, если оно будет использовать этот класс в виде поля класса или переменной внутри метода.

Ок, это какой-то хардкор, но можем рассмотреть и более простой пример:

static void UseFile(string filename, int position)
{
    using(var file = new FileStream(filename, FileMode.Open) {Position = position})
    { }
}


Ок, это тоже пример надуманный? вполне возможно, но всегда когда захват происходит не атомарно, то код перестает быть безопасным с точки зрения асинхронных исключений!




Проблема асинхронных исключений вообще и ThreadAbortException в частности, что мы не можем знать заранее, является ли исполняемый некоторым потоком код безопасным с точки зрения асинхронных исключений или нет. Этот код может успешно работать много лет и падать один раз в миллион вызовов. И тут дело не в детях и зажигалках, а в том, что мы не можем гарантировать, что наше приложение будет нормально работать при наличии асинхронных исключений, когда сам .NET Framework не гарантирует нормальную работу в этих условиях.

Вот и получается, что единственным безопасным вариантом вызова Thread.Abort является прекращение работы текущего потока, а обрыв другого потока всегда сопряжен с определенным риском, не зависимо от того, насколько вы доверяете себе и своему коду.

P.S. Достаточно погуглить на предмет количества различных утечек ресурсов (в частности файлов) при наличии Thread.Abort. Самый распространенные фиксятся, но я не думаю, что когда либо в ближайшем будущем .NET Framework станет безопасным с точки зрения асинхронных исключений;0
Re[3]: ReaderWriterLockSlim problems
От: drol  
Дата: 16.12.13 19:28
Оценка: 26 (1)
Здравствуйте, Аноним, Вы писали:

А>В каком здесь месте нарисовался Volatile.Write?


То есть с инкрементом owners Вы разобрались. Я Вас правильно понял ?

Теперь об ExitMyLock():

.method private hidebysig instance void  ExitMyLock() cil managed
{
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldflda     int32 System.Threading.ReaderWriterLockSlim::myLock
  IL_0006:  ldc.i4.0
  IL_0007:  call       void [mscorlib]System.Threading.Volatile::Write(int32&,
                                                                       int32)
  IL_000c:  ret
} // end of method ReaderWriterLockSlim::ExitMyLock


Дело в том, что всё не так просто. Начните с того, что посмотрите сколько разных файлов с названием System.Core.dll имеется в наличии у Вашей системы... И где они расположены...

>Передавайте привет декомпилерам, они такие классные, особенно бесплатные.


Привет не 21-летним сеньерам

А>Там не NUMA, там мало памяти (всего 16 Гб).


Объём не имеет никакого отношения к вопросу. Если в системе стоит два Xeon E5-2600, то обратиться к памяти соседа процессор может только через QPI-линк с ним. В отличии от своей собственной, с которой он соединён напрямую непосредственно контроллером памяти.

А>Рихтер предлагает свою библиотеку, она не рабочая.


Как ? И Рихтер тоже ?
Re[8]: ReaderWriterLockSlim problems
От: Аноним  
Дата: 16.12.13 19:33
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Проблема асинхронных исключений вообще и ThreadAbortException в частности, что мы не можем знать заранее, является ли исполняемый некоторым потоком код безопасным с точки зрения асинхронных исключений или нет. Этот код может успешно работать много лет и падать один раз в миллион вызовов. И тут дело не в детях и зажигалках, а в том, что мы не можем гарантировать, что наше приложение будет нормально работать при наличии асинхронных исключений, когда сам .NET Framework не гарантирует нормальную работу в этих условиях.

А в каких-каких местах он не гарантирует? Можно два-три примера, а то аж страшно представить что все сайты на ASP.NET — не нормально работающие приложения, ругулярно впрыскивающие в чужой код TBA.
Re[4]: ReaderWriterLockSlim problems
От: Аноним  
Дата: 16.12.13 20:11
Оценка:
Здравствуйте, drol, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>В каком здесь месте нарисовался Volatile.Write?


D>То есть с инкрементом owners Вы разобрались. Я Вас правильно понял ?


D>Теперь об ExitMyLock():


D>
D>.method private hidebysig instance void  ExitMyLock() cil managed
D>{
D>  // Code size       13 (0xd)
D>  .maxstack  8
D>  IL_0000:  ldarg.0
D>  IL_0001:  ldflda     int32 System.Threading.ReaderWriterLockSlim::myLock
D>  IL_0006:  ldc.i4.0
D>  IL_0007:  call       void [mscorlib]System.Threading.Volatile::Write(int32&,
D>                                                                       int32)
D>  IL_000c:  ret
D>} // end of method ReaderWriterLockSlim::ExitMyLock
D>


D>Дело в том, что всё не так просто. Начните с того, что посмотрите сколько разных файлов с названием System.Core.dll имеется в наличии у Вашей системы... И где они расположены...


Начну с того, что я привел код из памяти проблемной программы. На этом заканчиваю. Дальше не отвечаю, убеждать что проблема на твоем фреймворке и домашнем ПэКа отсутствует меня не нужно. Спасибо.
Re[5]: ReaderWriterLockSlim problems
От: drol  
Дата: 16.12.13 22:37
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Начну с того, что я привел код из памяти проблемной программы.


Не вопрос:

0:003> !dumpil 00007ffd79f53da0 
ilAddr = 00007ffd7a25c207
IL_0000: ldarg.0 
IL_0001: ldflda System.Threading.ReaderWriterLockSlim::myLock
IL_0006: ldc.i4.0 
IL_0007: call System.Threading.Volatile::Write
IL_000c: ret


Так что, для начала, я рекомендую Вам взять назад Ваши слова о декомпиляторах.

А>На этом заканчиваю.


А сколько понтов было в Вашем первом посте...

А>Дальше не отвечаю, убеждать что проблема на твоем фреймворке и домашнем ПэКа отсутствует меня не нужно.


Вы разговариваете сам с собой. Я не знаю существует проблема или нет. Я показываю, что Ваш анализ является поверхностным и бестолковым.
Re[8]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 22:45
Оценка:
ST>Ок, давай сделаем небольшую перезагрузку

ST>Рассмотрим такой код:

Я бы такой код назвал конечно наивной реализацией.
В приличных домах принято использовать PrepareConstrainedRegions()


По поводу /// using(var file = new FileStream
По сути проблема тут в самом Disposable паттерне.
В идеале в нём должен быть ещё один метод — метод аллокации ресурса,
тогда все вопросы с конструктором и соответственно присвоением переменной отпали бы.
Хотя и сейчас можно переписать компилятор и если присвоение делается в блоке юзинг то вначале присваивать результат переменной а уж потом вызывать конструктор.

ST>P.S. Достаточно погуглить на предмет количества различных утечек ресурсов (в частности файлов) при наличии Thread.Abort. Самый распространенные фиксятся, но я не думаю, что когда либо в ближайшем будущем .NET Framework станет безопасным с точки зрения асинхронных исключений;0

Он уже безопасен с некоторыми оговорками. Иначе его бы никогда не впихнули в сиквел.
Народная мудрось
всем все никому ничего(с).
Re[9]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 22:56
Оценка:
Забыл совсем сказать, когда бойцы прикручивали CLR к сиквелу — они изобрели HostProtectionAttribute у которого есть MayLeakOnAbort.
Если уже совсем страшно — то можно ориентироваться по нему.
Народная мудрось
всем все никому ничего(с).
Re[8]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 17.12.13 00:43
Оценка:
Кстате твой пример с FileStream безопасен более чем
Народная мудрось
всем все никому ничего(с).
Re[7]: ReaderWriterLockSlim problems
От: Sinix  
Дата: 17.12.13 05:05
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Проблемы с ThreadAbort у людей бывают когда они не понимают что это такое, когда выбрасывается и что с ним вообще делать надо.

Тут уже за меня ответили, причём в основном — гораздо лучше, чем я смогу.

Если суммировать: есть такая штука как bad practices. Их использование в 99.(9)% случаев означает, что у вас _уже_ возникла проблема на предыдущем шаге, но вместо решения самой проблемы вы пытаетесь подпереть её костылём. Ну, как заклеивать лампочку "проверьте двигатель" изолентой, чтоб не мешала. Исключения всегда бывают, но в основном хвастаться смотри ма, без рук "люди не понимают, а я могу" — это чистой воды ребячество.

И да, thread.Abort() — это bad practices в чистейшем дистиллированном виде.

Не, серьёзно — вы правда хотите протащить в продакшн проблемы, которые не воспроизводятся стабильно под отладкой?
Re[9]: ReaderWriterLockSlim problems
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 17.12.13 07:47
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Кстате твой пример с FileStream безопасен более чем


Этот код безопасен с точки зрения синхронных исключений (при учете, что setter свойства Position никтогда не бросает исключений), но с точки зрения асинхронных исключений?

static void UseFile(string filename, int position)
{
    var tmp = new FileStream(filename, FileMode.Open);
    var tmp.Position = position; // тут может упасть ThreadAbort
    using (var file = tmp) {}
}


В результате мы не потечем, но постусловие метода UseFile выполнено не будет, что может привести к каскаду проблем далее по коду.


З.Ы. ИМХО, использовать или не использовать Thread.Abort в своем коде — выбор каждого. Если ты считаешь, что потенциальные проблемы (данное обсуждение является примером того, что они возможны) не беспокоят — тогда ОК, вопрос в другом, если это именно твой код, то чем не устроили другие альтернативы? Если же это инфраструктура и выбора нет, то тут, собственно и обсуждать нечего.
Re[10]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 17.12.13 09:51
Оценка:
ST>Этот код безопасен с точки зрения синхронных исключений (при учете, что setter свойства Position никтогда не бросает исключений), но с точки зрения асинхронных исключений?
И и сточки зрения асинхронных он тоже безопасен.
Смысл в том что внутрях при вызове native функций используется SafeHandle по этому в принипе пофиг если исключение будет выкинуто в лдюбом месте.

ST>З.Ы. ИМХО, использовать или не использовать Thread.Abort в своем коде — выбор каждого. Если ты считаешь, что потенциальные проблемы (данное обсуждение является примером того, что они возможны) не беспокоят — тогда ОК

Я тебе про то что вероятность проблем очень сильно преувеличена и что уже давным давно придумали способы борьбы с асинхронными ислючениями в виде CER&Finally блока
Народная мудрось
всем все никому ничего(с).
Re[8]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 17.12.13 09:53
Оценка: -1
S>И да, thread.Abort() — это bad practices в чистейшем дистиллированном виде.
Передай это разработчикам сиквела, WCF и IIS-а а то они не вкурсе
Народная мудрось
всем все никому ничего(с).
Re[5]: ReaderWriterLockSlim problems
От: Аноним  
Дата: 17.12.13 10:39
Оценка:
Здравствуйте, Аноним, Вы писали:

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


D>>Здравствуйте, Аноним, Вы писали:


А>>>В каком здесь месте нарисовался Volatile.Write?


D>>То есть с инкрементом owners Вы разобрались. Я Вас правильно понял ?


D>>Теперь об ExitMyLock():


D>>
D>>.method private hidebysig instance void  ExitMyLock() cil managed
D>>{
D>>  // Code size       13 (0xd)
D>>  .maxstack  8
D>>  IL_0000:  ldarg.0
D>>  IL_0001:  ldflda     int32 System.Threading.ReaderWriterLockSlim::myLock
D>>  IL_0006:  ldc.i4.0
D>>  IL_0007:  call       void [mscorlib]System.Threading.Volatile::Write(int32&,
D>>                                                                       int32)
D>>  IL_000c:  ret
D>>} // end of method ReaderWriterLockSlim::ExitMyLock
D>>


D>>Дело в том, что всё не так просто. Начните с того, что посмотрите сколько разных файлов с названием System.Core.dll имеется в наличии у Вашей системы... И где они расположены...


А>Начну с того, что я привел код из памяти проблемной программы. На этом заканчиваю. Дальше не отвечаю, убеждать что проблема на твоем фреймворке и домашнем ПэКа отсутствует меня не нужно. Спасибо.


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

V>Да. Но volatile — это не синхронизация доступа. Это только указание компилятору не кэшировать обращения к переменой.

Это неправда. Операции над volatile-полями включают в себя acquire\release семантику. Посему на них вполне можно делать массу разновидностей синхронизации. Только понимать надо что к чему когда и где...

при этом понятия не имеет что такое acquire\release

в общем — не парься
Re[9]: ReaderWriterLockSlim problems
От: Sinix  
Дата: 17.12.13 10:41
Оценка: +2
Здравствуйте, Tom, Вы писали:

Tom>Передай это разработчикам сиквела, WCF и IIS-а а то они не вкурсе

Это очень рискованное заявление

Конкретно про ms sql я могу и поспорить, т.к. лет семь назад копался в нюансах реализации hosted clr. Если коротко, по памяти и не совсем корректно (как всегда есть нюансы): при разработке под ms sql нужно соблюдать ряд ограничений, в частности — недопустимо использование разделяемого состояния/static-полей. В том числе и по причине возможного thread.Abort() (хотя там не совсем классический .Abort()).

В принципе, можно на рекомендации наплевать, тогда придётся или плодить сer (бонусом — лаги и невозможность использование untrusted сборок), или бороться с битым состоянием для отдельных запросов (сессий). Оно конечно лечится через выгрузку sqlclr appdomain, но всё равно неприятно.

Про wcf/iis — очень интересно. Где там используется thread.Abort()? Appdomain recycling не считается по вполне понятным причинам
Re[6]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 17.12.13 11:25
Оценка: :)
А>при этом понятия не имеет что такое acquire\release
И что это такое?
Народная мудрось
всем все никому ничего(с).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.