2015-09-10 13 views
14

Dzisiaj próbowałem wytłumaczyć współpracownikowi, że ||= nie jest bezpieczny dla wątków w MRI. Pomyślałem, że przyjrzę się źródłu Ruby i spróbuję sprawdzić, czy mogę wskazać miejsce, w którym program planujący Ruby może zmienić kontekst wątku, ale mam problem z nawigacją po kodzie. Miałem nadzieję, że ktoś bardziej doświadczony może przejść przez pliki, które zostały trafione.W jaki sposób MRI analizuje operatory `|| =`?

Do tej pory wiem, że Bison pobiera parse.y i generuje plik parse.c, który wywołuje niektóre podstawowe funkcje. Widzę, że || jest parsowany jako tOROP, ale potem tracę trochę na tym, co stanie się dalej

Czy jest też jakieś narzędzie, takie jak Ripper, którego mogę użyć, aby ułatwić ten proces? (I w tym przypadku byłoby pomocne, gdyby ktoś mógł wskazać mi gdzie jest zdefiniowany kod źródłowy Rippera)

+1

To operacja nieatomowa, więc nie jest bezpieczna dla wątków. Jakie jest konkretne pytanie? Jeśli potrzebujesz bezpieczeństwa wątku, musisz o to poprosić. – tadman

+0

Co czyni go nieatomowym? Chciałbym móc śledzić kod źródłowy, aby zobaczyć, co sprawia, że ​​to prawda. –

+3

Tak jak 'x + = 1' jest nieatomowy. Wymaga odczytu, porównania i (warunkowego) przypisania. 'x || = y' jest efektywnie' x = x || y' lub 'x = y chyba (x)' w zależności od tego, jak konkretnie chcesz się dostać. Zauważ, że w obu przypadkach przed przypisaniem wymagane jest przeczytanie i porównanie (nie * false *). Wszystko może się zdarzyć w tej luce. Możesz przyjrzeć się temu, co MRI kodu bajtowego wyraża to stwierdzenie, aby wiedzieć, co dzieje się wewnętrznie. – tadman

Odpowiedz

1

Zapominając o parserze, jeśli spojrzysz na kod in compile.c here zobaczysz, jak generowane są instrukcje do obsługi cesja - lub operacja. Każde wywołanie ADD_INSNL powoduje wysłanie instrukcji. W linii 4553 widzisz warunek jeśli, który testuje wartość LHS po przeczytaniu przez kod emitowany przez wywołanie makra KOMPILACJA w linii 4546, aby zdecydować, czy przypisać nową wartość. W tym czasie inny wątek może nadpisywać i zmieniać wartość, która została odczytana, więc przydział jest wykonywany (lub nie jest wykonywany), kiedy nie powinien być.

Jeśli chodzi o sposób tworzenia NODE_OP_ASGN_OR, zobacz wywołanie NEW_OP_ASGN_OR (zdefiniowane w node.h) wywoływane z parse.y w funkcji new_op_assign_gen().

Mam nadzieję, że numery linii nie zmienią się zbyt wcześnie i unieważnią te adresy URL.

Powiązane problemy