Передача сообщений от деструктора во время сборки мусора - PullRequest
5 голосов
/ 23 апреля 2011

Следующее дает мне Нарушение прав доступа в Windows 32-bit, dmd.2.052, без флагов.Когда деструктор запускается сборщиком мусора, окно сообщения кажется поврежденным в процессе.

import std.stdio;
import core.thread;
import core.memory;
import std.concurrency;

class C
{
    string m_str;
    Tid m_receiverTid;
    this(string s, Tid rt) { this.m_str = s; this.m_receiverTid = rt; }
    ~this() {   writeln("Destructor : ",this.m_str);
                m_receiverTid.send(this.m_str);
            }
}


void receiver() {
        try {
            while(true) {
                receive((string s){writeln("Received: ",s);});
            }
        } catch (Throwable th) {
            writeln("Caught throwable: ",th.toString());
        }
}

void main() {
    Tid receiverTid = spawn(&receiver);

    receiverTid.send("Basic test");
    Thread.sleep( 5_000_000 );

    C c1 = new C("c1 Manually deleted",receiverTid);
    delete c1;
    Thread.sleep( 5_000_000 );

    {
        C c2 = new C("c2 Garbage collected",receiverTid);
    }
    writeln("Running garbage collector..."); // This line needed to flush out the c2 root pointer.
    GC.collect();
    Thread.sleep( 5_000_000 );

    writeln("Exiting main thread...");
}

Выше приведено:

Получено: Базовый тест
Деструктор: c1 Удалено вручную
Получено: c1 Удалено вручную
Запущен сборщик мусора ...
Деструктор: c2 Сборка мусора
Получено: Сборка мусора c2
Поймано с возможностью выброса: object.Error: Нарушение прав доступа
Выход из основного потока ...

Есть ли обходные пути для этого?
Есть ли способ для кода деструктора узнать, вызывается ли он GC или нет?
Является ли передача сообщений от деструктора по сути небезопасной, например, если потоки, не относящиеся к GC, замораживаются GC, в то время как они имеют блокировку мьютекса в окне общего сообщения, тогда GC может зайти в тупик, если он отправляет сообщение в заблокированное окно сообщения?Или код деструктора выполняется только в цикле очистки после размораживания всех потоков?
Безопасно ли для деструктора ссылаться на локальное хранилище потока, например, может ли цикл очистки GC находиться в другом потоке?

1 Ответ

5 голосов
/ 23 апреля 2011

Я вижу здесь две проблемы, которые могут быть связаны.Во-первых, ссылка на подобъекты из деструктора, вызываемого GC, не допускается.

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

Во-вторых, как вы упомянули, вызовы деструкторов происходят только в цикле очистки после возобновления всех потоков.Они могут быть вызваны из другого потока, чем тот, которому принадлежал объект, когда он был жив.На столе есть предложения, чтобы это исправить, но пока ни одно из них не было реализовано.

...