Comment #0 by john.loughran.colvin — 2012-12-07T06:04:25Z
import std.concurrency;
import std.stdio;
void foo() {
bool running = true;
while(running) {
receive(
(immutable(double)[] a, immutable(double)[] b, int i) {
writeln(a, b, i);
},
(OwnerTerminated e) {
running = false;
}
);
}
}
void main() {
double[] a,b;
a = [1.1];
b = [2.2];
int i= 3;
auto tid = spawn(&foo);
tid.send(a.idup, b.idup, i);
}
I get: core.exception.AssertError@ std/variant.d(277): target must be non-null
Comment #1 by david — 2013-01-03T04:44:21Z
This is probably related to issue 7069.
The problem also occurs on structs like this:
import std.concurrency, std.exception, std.stdio;
struct Combined
{
string str1;
string str2;
bool status;
}
void main() {
auto tid = spawn(&worker);
Combined c = Combined("one", "two", false);
tid.send(c);
}
void worker() {
for (bool running = true; running; )
{
receive(
(Combined c)
{
writeln("Got ", c.str1, "\t", c.str2, "\t", c.status);
},
(OwnerTerminated unused)
{
running = false;
}
);
}
}
Comment #2 by david — 2013-01-03T05:51:35Z
Bumping importance. This issue makes it impossible for me to move to 2.061 because it breaks all my applications that use message passing for concurrency.
Comment #3 by mk — 2013-03-31T15:59:08Z
Code from comment #1 works for me in 32 bit, but I get the same error message ("target must be non-null") when the size of a message (Combined.sizeof) exceeds 24 bytes.
Comment #4 by zheny — 2013-04-19T10:02:44Z
Is anyone working on this issue?
Comment #5 by octavian.cacina — 2013-04-23T11:45:43Z
I hit this bug too as I wanted to send a structure. Martin Krejcirik was right about the size of the structure. As soon as the message to be sent exceeds 20 bytes (win32) it comes to the assert. I see that the problem is with the default generated opAssign for the struct Message in std.concurrency. This Message has a "Variant data" attribute that needs to be copied.
I could reproduce the error like this:
---
struct S { int p1, p2, p3, p4, p5, p6; }
Variant v1 = S();
Variant v2;
v2 = v1; // assert
---
The Variant is defined like:
alias VariantN!(maxSize!(creal, char[], void delegate())) Variant;
so it has already a fixed size. The constructor can cope with the bigger size and will adjust, but the opAssign does not. I do not know if it is a bug that the constructor allows it or that the opAssign does not.
A possible fix would be to add an opAssign operator to the Message structure:
---
ref Message opAssign(Message rhs)
{
type = rhs.type;
swap(data, rhs.data);
return this;
}
---
Comment #6 by code — 2013-05-14T20:07:55Z
(In reply to comment #5)
> The Variant is defined like:
> alias VariantN!(maxSize!(creal, char[], void delegate())) Variant;
> so it has already a fixed size. The constructor can cope with the bigger size
> and will adjust, but the opAssign does not.
OpAssign moves the assigned value onto the heap so this is not the problem.
https://github.com/D-Programming-Language/phobos/blob/c319b1578f28e00124d2f0c2a492790d01ca5159/std/variant.d#L545
Also the following code works correctly for me on 2.062.
---
import std.variant, std.stdio;
struct S { int p1, p2, p3, p4, p5, p6; }
void main()
{
Variant v1 = S(1, 2, 3, 4, 5, 6);
writeln(v1);
Variant v2;
writeln(v2);
v2 = v1; // assert
writeln(v2);
}
---
The bug seems to be in the handler for OpID.copyOut.
Comment #7 by octavian.cacina — 2013-05-14T23:54:37Z
(In reply to comment #6)
>
> Also the following code works correctly for me on 2.062.
yes, here I have a wrong sample, the structure size must exceed 32bytes. The S should be: struct S { int[9] s; }
See #10017 - Can not assign to a Variant another Variant holding a bigger structure
I also made a pull request for it ( https://github.com/D-Programming-Language/phobos/pull/1281 ) but David Nadlinger wants to fix the fact that these Variant assignments trigger a reallocation even if there already is a heap value (comments in pull).