Skip to content

Commit

Permalink
ae.sys: Fix for dlang/dmd#10644
Browse files Browse the repository at this point in the history
Address a questionable approach to synchronization on the way.
  • Loading branch information
CyberShadow committed Dec 11, 2019
1 parent 9841561 commit 6ea2a12
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
23 changes: 18 additions & 5 deletions sys/shutdown.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@ module ae.sys.shutdown;
/// Warning: the delegate may be called in an arbitrary thread.
void addShutdownHandler(void delegate() fn)
{
if (handlers.length == 0)
register();
handlers ~= fn;
handlers.add(fn);
}

/// Calls all registered handlers.
void shutdown()
{
foreach (fn; handlers)
foreach (fn; handlers.get())
fn();
}

Expand Down Expand Up @@ -123,4 +121,19 @@ void register()
}
}

shared void delegate()[] handlers;
synchronized class HandlerSet
{
alias T = void delegate();
private T[] handlers;

void add(T fn)
{
if (handlers.length == 0)
register();
handlers ~= cast(shared)fn;
}
const(T)[] get() { return cast(const(T[]))handlers; }
}

shared HandlerSet handlers;
shared static this() { handlers = new HandlerSet; }
51 changes: 36 additions & 15 deletions sys/signals.d
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,18 @@ version(FreeBSD) private

void addSignalHandler(int signum, SignalHandler fn)
{
if (handlers[signum].length == 0)
{
handlers[signum].add(fn, {
alias sigfn_t = typeof(signal(0, null));
auto old = signal(signum, cast(sigfn_t)&sighandle);
assert(old == SIG_DFL || old == SIG_IGN, "A signal handler was already set");
}
handlers[signum] ~= fn;
});
}

void removeSignalHandler(int signum, SignalHandler fn)
{
foreach (i, lfn; handlers[signum])
if (lfn is fn)
{
handlers[signum] = handlers[signum][0..i] ~ handlers[signum][i+1..$];
if (handlers[signum].length == 0)
signal(signum, SIG_DFL);
return;
}
assert(0);
handlers[signum].remove(fn, {
signal(signum, SIG_DFL);
});
}

// ***************************************************************************
Expand Down Expand Up @@ -107,11 +99,40 @@ bool collectSignal(int signum, void delegate() code)
private:

enum SIGMAX = 100;
shared SignalHandler[][SIGMAX] handlers;

synchronized class HandlerSet
{
alias T = SignalHandler;
private T[] handlers;

void add(T fn, scope void delegate() register)
{
if (handlers.length == 0)
register();
handlers ~= cast(shared)fn;
}
void remove(T fn, scope void delegate() deregister)
{
foreach (i, lfn; handlers)
if (lfn is fn)
{
handlers = handlers[0..i] ~ handlers[i+1..$];
if (handlers.length == 0)
deregister();
return;
}
assert(0);
}
const(T)[] get() pure nothrow @nogc { return cast(const(T[]))handlers; }
}

shared HandlerSet[SIGMAX] handlers;

shared static this() { foreach (ref h; handlers) h = new HandlerSet; }

extern(C) void sighandle(int signum) nothrow @system
{
if (signum >= 0 && signum < handlers.length)
foreach (fn; handlers[signum])
foreach (fn; handlers[signum].get())
fn();
}

0 comments on commit 6ea2a12

Please sign in to comment.