Re: Weird bug in std.logger? Possible memory corruption
On 1/11/23 18:26, Christian Köstlin wrote: It's really weird: https://run.dlang.io/is/fIBR2n I think I might have found out the issue. It's indeed related to the lazy parameter and reentrance. The usual logger functions consist of three parts: a header, the message, and the "finalizer". [1]. Internally this is implemented using a string appender [2, 3]. However, this string appender is a member of the class, and this is the source of the bug, because it's shared among all the calls to the logger. It's usually protected by a mutex, so different threads don't mess with each other, but it didn't take reentrancy into account. And so the call to the logging function within `foo` takes place once the appender is already populated, so this is what happens: 1. Header of first call to `log` (`info`, in this case, but it's irrelevant). 2. Body of first invocation -> Call to `foo()` -> Second call to `log`. 3. The buffer is cleared: The first header is discarded (and previous body, if there were any). 4. The second invocation proceeds normally, and the control returns to the first invocation 5. Now the buffer contains the full content of the previous call, and the return of `foo` is added. This is exactly what we see. If we do an assignment **before**, then the call is no longer reentrant and everything happens as expected. So I'd still call it a bug, but at least there seems to be no memory corruption. Also, it doesn't have an easy way to fix it without changing the interface (and potentially affecting already existing custom implementations). In my view, `writeLogMsg` should create a brand new appender (not a member of the class) that would be passed as a parameter to `beginLogMsg`, `logMsgPart` and `finishLogMsg()`. Anyway, I think the mystery is more or less solved. [1]: https://dlang.org/phobos/std_logger_core.html#.Logger [2]: https://github.com/dlang/phobos/blob/master/std/logger/core.d#L1401 [3]: https://github.com/dlang/phobos/blob/master/std/logger/core.d#L619-L641
Re: Weird bug in std.logger? Possible memory corruption
On Wednesday, 1 November 2023 at 17:26:42 UTC, Christian Köstlin wrote: ... It's really weird: https://run.dlang.io/is/fIBR2n Interesting because I wrote a similar test as you did. And that increment (Or lack of) called my attention, If I can I'll try and take a look at that (std.logger) info() Implementation later after work. Matheus.
Re: Weird bug in std.logger? Possible memory corruption
On Wednesday, 1 November 2023 at 14:15:55 UTC, matheus wrote: On Tuesday, 31 October 2023 at 21:19:34 UTC, Arafel wrote: ... Assigning the value to a variable works as expected: ```d import std.logger : info; void main() { auto s = foo(); info(s); } auto foo() { info("In foo"); return "Hello, world."; } ``` ... Unless you do: string s; info(s=foo()); I think this is a bug, or at least very weird behavior. Matheus. It's really weird: https://run.dlang.io/is/fIBR2n
Re: Weird bug in std.logger? Possible memory corruption
On Tuesday, 31 October 2023 at 21:19:34 UTC, Arafel wrote: ... Assigning the value to a variable works as expected: ```d import std.logger : info; void main() { auto s = foo(); info(s); } auto foo() { info("In foo"); return "Hello, world."; } ``` ... Unless you do: string s; info(s=foo()); I think this is a bug, or at least very weird behavior. Matheus.
Re: Weird bug in std.logger? Possible memory corruption
I can only imagine that it's related to the logging functions taking lazy arguments, although I cannot see why it would be a problem in a simple case like this. I've been thinking a bit more about it, and it must be indeed because of the lazy argument. `foo()` is an argument to `info`, but it also uses the logger. However, because it's a lazy argument, it's not called from `main`, but from `info` itself. I strongly suspect that the problem is that it's not reentrant. I'm not clear what it's supposed to happen, but assuming this case won't be supported, it should at least be documented. Should I open a bug about it?
Weird bug in std.logger? Possible memory corruption
Hi, Today I have just found a weird bug in std.logger. Consider: ```d import std.logger : info; void main() { info(foo()); } auto foo() { info("In foo"); return "Hello, world."; } ``` The output is: ``` 2023-10-31T20:41:05.274 [info] onlineapp.d:8:foo In foo 2023-10-31T20:41:05.274 [info] onlineapp.d:8:foo In fooHello, world. ``` The second line is obviously wrong, as it repeats the first line as its header. That's why I suspect memory corruption. Assigning the value to a variable works as expected: ```d import std.logger : info; void main() { auto s = foo(); info(s); } auto foo() { info("In foo"); return "Hello, world."; } ``` gets the proper output: ``` 2023-10-31T21:09:46.529 [info] onlineapp.d:9:foo In foo 2023-10-31T21:09:46.529 [info] onlineapp.d:5:main Hello, world. ``` I can only imagine that it's related to the logging functions taking lazy arguments, although I cannot see why it would be a problem in a simple case like this.
Re: Weird floating point rounding - Bug or how to control it correctly
On Thursday, 14 September 2023 at 03:23:48 UTC, An Pham wrote: import std.stdio; void main() { float f = 6394763.345f; import std.format : sformat; char[80] vBuffer = void; writeln("6394763.345 = ", sformat(vBuffer[], "%.4f", f)); } Output 6394763.345 = 6394763.5000 Classic question. The float literal `6394763.345f` is not representable as IEEE-754 floating point number. Try https://www.h-schmidt.net/FloatConverter/IEEE754.html for a short introduction to the issue.
Re: Weird floating point rounding - Bug or how to control it correctly
On Wednesday, September 13, 2023 9:23:48 PM MDT An Pham via Digitalmars-d- learn wrote: > import std.stdio; > > void main() > { > float f = 6394763.345f; > > import std.format : sformat; > > char[80] vBuffer = void; > writeln("6394763.345 = ", sformat(vBuffer[], "%.4f", f)); > > } > > Output > 6394763.345 = 6394763.5000 The nature of floating point numbers is such that there a bunch of values that they can't actually represent, and they get rounded pretty easily depending on the exact numbers involved. So, in general, you shouldn't expect floating point numbers to be exact. You will generally do better with increased precision though, and in this case, it looks like your number will stay the same if you use double or real instead of float. I would suggest that you watch this video from dconf 2016 which discusses floating point values: https://www.youtube.com/watch?v=YEUAUnamQiA - Jonathan M Davis
Weird floating point rounding - Bug or how to control it correctly
import std.stdio; void main() { float f = 6394763.345f; import std.format : sformat; char[80] vBuffer = void; writeln("6394763.345 = ", sformat(vBuffer[], "%.4f", f)); } Output 6394763.345 = 6394763.5000
Re: Bug in usage of associative array: dynamic array with string as a key
On 6/30/23 17:42, Cecil Ward wrote: > https://dlang.org/spec/hash-map.html#testing_membership in the language > docs, under associative arrays - 13.3 testing membership. Would anyone > else care to try that example out as that might be quicker? I tried it by 1) Putting all the code inside a 'void main()' function 2) Pasting the code from the top of that page and it works: void main() { int[string] aa; // Associative array of ints that are // indexed by string keys. // The KeyType is string. aa["hello"] = 3; // set value associated with key "hello" to 3 int value = aa["hello"]; // lookup value from a key assert(value == 3); int* p; p = "hello" in aa; if (p !is null) { *p = 4; // update value associated with key assert(aa["hello"] == 4); } } > the only substantive > change being deleting the variable p Do you mean this: aa.remove("hello"); That works too. D's associative arrays have a few quirks but they work just fine. They are not buggy as it may be inferred from some of the posts here. Ali
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 19:05:23 UTC, Cecil Ward wrote: I have code roughly like the following: dstring str = "name"d; uint ordinal = (( str in Decls.ordinals ) !is null) ? Decls.ordinals[ str ] : -1; struct Decls { uint[ dstring] ordinals; } //and Decls.ordinals[ str ] = ordinal_counter++; The problem is that it always returns ordinal== -1 from the expression. Can you sort me out? I took this from the example given in the language reference under arrays, testing for membership (or similar, I forget the subssection title). From good old printfs it seems to be the case that the array is being populated (elsewhere) with the expected correct values. Taking out the if doesn’t seem to help either. I don’t have a way of examining the contents of the dynamic array directly to check that they are actually being stored as expected, other than seeing that that line of code is indeed being executed with the expected values of str going in. Note that I’m using 32-bit dstrings everywhere, not strings of bytes. Fool that I am. I did those good old printfs a while back, and now I recheck them I see that something has become broken and it seems that the insertions are not happening now. So thankyou for your kindness and I’ll post again if that doesn’t solve the non-issue.
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 21:25:23 UTC, H. S. Teoh wrote: On Fri, Jun 30, 2023 at 07:05:23PM +, Cecil Ward via Digitalmars-d-learn wrote: [...] It would help if you could post the complete code that reproduces the problem. Or, if you do not wish to reveal your code, reduce it to a minimal case that still exhibits the same problem, so that we can see it for ourselves. The snippets you provided do not provide enough information to identify the problem. T I would indeed need to cut it down massively, as the original code is ~2k lines. Mind you, I will just end up with the example at https://dlang.org/spec/hash-map.html#testing_membership in the language docs, under associative arrays - 13.3 testing membership. Would anyone else care to try that example out as that might be quicker? That’s because as all I did was copy that basically, with the only substantive change being deleting the variable p, but I’m still testing whether or not I get a null pointer. I thought I had checked that the insertions were all as expected, so I’ll go and recheck that next.
Re: Bug in usage of associative array: dynamic array with string as a key
https://forum.dlang.org/thread/duetqujuoceancqtj...@forum.dlang.org Try HashMap see if it is still a problem. If no, then it's another example of the built in AA problem.
Re: Bug in usage of associative array: dynamic array with string as a key
On Fri, Jun 30, 2023 at 07:05:23PM +, Cecil Ward via Digitalmars-d-learn wrote: [...] It would help if you could post the complete code that reproduces the problem. Or, if you do not wish to reveal your code, reduce it to a minimal case that still exhibits the same problem, so that we can see it for ourselves. The snippets you provided do not provide enough information to identify the problem. T -- What's the difference between a 4D tube and an overweight Dutchman? One is a hollow spherinder, and the other is a spherical Hollander.
Re: Bug in usage of associative array: dynamic array with string as a key
On 6/30/23 13:16, Cecil Ward wrote: On Friday, 30 June 2023 at 19:58:39 UTC, FeepingCreature wrote: Note that you can do `uint ordinal = Decls.ordinals.get(str, -1);`. Is the second argument an ‘else’ then, my friend? Yes, .get and friends appear in this table: https://dlang.org/spec/hash-map.html#properties Ali
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 19:58:39 UTC, FeepingCreature wrote: On Friday, 30 June 2023 at 19:05:23 UTC, Cecil Ward wrote: I have code roughly like the following: dstring str = "name"d; uint ordinal = (( str in Decls.ordinals ) !is null) ? Decls.ordinals[ str ] : -1; struct Decls { uint[ dstring] ordinals; } //and Decls.ordinals[ str ] = ordinal_counter++; The problem is that it always returns ordinal== -1 from the expression. Can you sort me out? Impossible to tell without a complete repro, I'm afraid. The expression, at least, looks correct at first glance. Note that you can do `uint ordinal = Decls.ordinals.get(str, -1);`. Is the second argument an ‘else’ then, my friend?
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 20:12:08 UTC, Ali Çehreli wrote: On 6/30/23 12:05, Cecil Ward wrote: > I have code roughly like the following: > > dstring str = "name"d; Aside: One almost never needs dstring. > uint ordinal = (( str in Decls.ordinals ) !is null) ? > Decls.ordinals[ str ] : -1; > > struct Decls > { > uint[ dstring] ordinals; Do you mean 'ordinals' is 'static'? Otherwise, Decls.ordinals does not compile. > } > > //and > Decls.ordinals[ str ] = ordinal_counter++; Are you doing that *after* you initialize 'ordinal' as you show here? :) Ali Hi Ali, ‘ordinal’ is a static initialised explicitly with zero.
Re: Bug in usage of associative array: dynamic array with string as a key
On 6/30/23 12:05, Cecil Ward wrote: > I have code roughly like the following: > > dstring str = "name"d; Aside: One almost never needs dstring. > uint ordinal = (( str in Decls.ordinals ) !is null) ? > Decls.ordinals[ str ] : -1; > > struct Decls > { > uint[ dstring] ordinals; Do you mean 'ordinals' is 'static'? Otherwise, Decls.ordinals does not compile. > } > > //and > Decls.ordinals[ str ] = ordinal_counter++; Are you doing that *after* you initialize 'ordinal' as you show here? :) Ali
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 19:05:23 UTC, Cecil Ward wrote: I have code roughly like the following: dstring str = "name"d; uint ordinal = (( str in Decls.ordinals ) !is null) ? Decls.ordinals[ str ] : -1; struct Decls { uint[ dstring] ordinals; } //and Decls.ordinals[ str ] = ordinal_counter++; The problem is that it always returns ordinal== -1 from the expression. Can you sort me out? Impossible to tell without a complete repro, I'm afraid. The expression, at least, looks correct at first glance. Note that you can do `uint ordinal = Decls.ordinals.get(str, -1);`.
Bug in usage of associative array: dynamic array with string as a key
I have code roughly like the following: dstring str = "name"d; uint ordinal = (( str in Decls.ordinals ) !is null) ? Decls.ordinals[ str ] : -1; struct Decls { uint[ dstring] ordinals; } //and Decls.ordinals[ str ] = ordinal_counter++; The problem is that it always returns ordinal== -1 from the expression. Can you sort me out? I took this from the example given in the language reference under arrays, testing for membership (or similar, I forget the subssection title). From good old printfs it seems to be the case that the array is being populated (elsewhere) with the expected correct values. Taking out the if doesn’t seem to help either. I don’t have a way of examining the contents of the dynamic array directly to check that they are actually being stored as expected, other than seeing that that line of code is indeed being executed with the expected values of str going in. Note that I’m using 32-bit dstrings everywhere, not strings of bytes.
Re: looking for hint to debug a strange multi-thread bug (grpc-d-core)
UPDATE: life is too short to debug dlang built-in AA to right, let's just use HashMap from emsi_containers https://github.com/mw66/grpc-d/blob/master/source/grpc/server/package.d#L25 ``` HashMap!(string, ServiceHandlerInterface) services; ``` After this change, the problem goes away. I think there are some bugs in the builtin AA implementation, as demo-ed in this multi-threaded program (maybe also related to GC?).
looking for hint to debug a strange multi-thread bug (grpc-d-core)
Hi, I recently found and started playing with the grpc-d-core[1] package, and my program structure looks like this: https://github.com/mw66/grpc-demo/blob/master/source/main.d If I run L64 alone (without L66 ~ 79 grpc-d part): ``` 64: auto t = new Thread({fun();}).start(); ``` it works fine. If I run L66 ~ 79 grpc-d part alone (without L64), it also works fine. But if I run both, the program received signal SIGSEGV, Segmentation fault at here: https://github.com/mw66/grpc-d/blob/master/source/grpc/server/package.d#L94 with LDC, the print out of `services.keys` shows its corrupted with some strange values. under DMD, it fails at: https://github.com/mw66/grpc-d/blob/master/source/grpc/server/package.d#L99 while the `services.keys` seems fine. What puzzles me is that: these two parts of the code are actually independent, does not know each other at all (as I just started to add the grpc-d skeleton code with dummy returns, and no client connected or made any rpc calls). And the `services` defined here is a private class field: https://github.com/mw66/grpc-d/blob/master/source/grpc/server/package.d#L21 So how can it be corrupted by `fun()`? Any suggestions where should I look into? Thanks. [1] https://code.dlang.org/packages/grpc-d-core
Re: Is this a bug?
On Thursday, 16 March 2023 at 04:31:11 UTC, Elfstone wrote: On Thursday, 16 March 2023 at 04:04:51 UTC, Elfstone wrote: On Thursday, 16 March 2023 at 03:44:19 UTC, Elfstone wrote: [...] Correction. With or without comments, mostly it doesn't compile, occasionally it does! I have no idea. I can't get it to compile anymore, it must be some mistake from me. Maybe I forgot to save while modifying the code. So the `S` declared in `is` expression can contaminate the scope? Is this supposed to happen? Never mind, I just found out this is supposed to happen, `S` is supposed to be available later. https://dlang.org/spec/expression.html#is-parameter-list
Re: Is this a bug?
On Thursday, 16 March 2023 at 04:04:51 UTC, Elfstone wrote: On Thursday, 16 March 2023 at 03:44:19 UTC, Elfstone wrote: On Thursday, 16 March 2023 at 03:40:04 UTC, Elfstone wrote: [...] Oops, the above code compiles, because I added comments!!! Now this really doesn't compile: ```D struct Matrix(S, size_t M, size_t N) { } alias Vec3(S) = Matrix!(S, 3, 1); void main() { import std.stdio; writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); writeln(is(Matrix!(float, 3, 1) == Matrix!(S, 3, 1), S)); } ``` Correction. With or without comments, mostly it doesn't compile, occasionally it does! I have no idea. I can't get it to compile anymore, it must be some mistake from me. Maybe I forgot to save while modifying the code. So the `S` declared in `is` expression can contaminate the scope? Is this supposed to happen?
Re: Is this a bug?
On Thursday, 16 March 2023 at 03:44:19 UTC, Elfstone wrote: On Thursday, 16 March 2023 at 03:40:04 UTC, Elfstone wrote: [...] Oops, the above code compiles, because I added comments!!! Now this really doesn't compile: ```D struct Matrix(S, size_t M, size_t N) { } alias Vec3(S) = Matrix!(S, 3, 1); void main() { import std.stdio; writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); writeln(is(Matrix!(float, 3, 1) == Matrix!(S, 3, 1), S)); } ``` Correction. With or without comments, mostly it doesn't compile, occasionally it does! I have no idea.
Is this a bug?
```D struct Matrix(S, size_t M, size_t N) { } alias Vec3(S) = Matrix!(S, 3, 1); void main() { import std.stdio; writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); // `alias` `S` is defined here writeln(is(Matrix!(float, 3, 1) == Matrix!(S, 3, 1), S)); // Error: declaration `S` is already defined } ``` Even though the following code compiles. ```D writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); ```
Re: Is this a bug?
On Thursday, 16 March 2023 at 03:40:04 UTC, Elfstone wrote: ```D struct Matrix(S, size_t M, size_t N) { } alias Vec3(S) = Matrix!(S, 3, 1); void main() { import std.stdio; writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); // `alias` `S` is defined here writeln(is(Matrix!(float, 3, 1) == Matrix!(S, 3, 1), S)); // Error: declaration `S` is already defined } ``` Even though the following code compiles. ```D writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); ``` Oops, the above code compiles, because I added comments!!! Now this really doesn't compile: ```D struct Matrix(S, size_t M, size_t N) { } alias Vec3(S) = Matrix!(S, 3, 1); void main() { import std.stdio; writeln(is(Vec3!float == Matrix!(S, 3, 1), S)); writeln(is(Matrix!(float, 3, 1) == Matrix!(S, 3, 1), S)); } ```
Re: Bug in DMD?
On Friday, 3 March 2023 at 01:37:42 UTC, Richard (Rikki) Andrew Cattermole wrote: On 03/03/2023 2:33 PM, ryuukk_ wrote: So it is a DMD bug? Yes and thanks to you I can now say that we can absolutely get rid of DllMain requirement for DLLs! glad the outcome is positive, and i apologies about earlier comments, i may have sounded a little bit rude
Re: Bug in DMD?
On Friday, 3 March 2023 at 01:21:52 UTC, ryuukk_ wrote: I have some questions: 1. why does it work with LDC? 2. why does it work with DMD when build/link in 2 step? 3. why it doesn't work when DMD is invoked once for build/link I think these are probably coincidences and the answer can be summarized as "that's what ends up happening due to the details of the implementation". 4. is this a bug in DMD or my code is wrong? I would say the code is wrong in principle, though as you've noted it can still work in some specific circumstances. 5. if it's wrong, then why does it compile/no error? `extern(C) main` is a low-level feature, because it effectively turns off parts of the language. However, the rest of the program doesn't know that this is the case - currently the compiler simply assumes you know what you're doing. Maybe it's not OK that it's easy to use it by accident.
Re: Bug in DMD?
I added a note here: https://issues.dlang.org/show_bug.cgi?id=20737
Re: Bug in DMD?
On 03/03/2023 2:33 PM, ryuukk_ wrote: So it is a DMD bug? Yes and thanks to you I can now say that we can absolutely get rid of DllMain requirement for DLLs!
Re: Bug in DMD?
On Friday, 3 March 2023 at 01:24:42 UTC, Richard (Rikki) Andrew Cattermole wrote: This works: ```d extern(C) void main() { Stuff[5] temp = [ Stuff(), Stuff(), Stuff(), Stuff(), Stuff(), ]; stuffs = temp[]; stuffs[0].do_something(); } ``` ```d Stuff[] stuffs; ``` The problem here is dmd isn't initializing TLS with a value, but TLS itself is working. So it is a DMD bug?
Re: Bug in DMD?
This works: ```d extern(C) void main() { Stuff[5] temp = [ Stuff(), Stuff(), Stuff(), Stuff(), Stuff(), ]; stuffs = temp[]; stuffs[0].do_something(); } ``` ```d Stuff[] stuffs; ``` The problem here is dmd isn't initializing TLS with a value, but TLS itself is working.
Re: Bug in DMD?
On Friday, 3 March 2023 at 01:11:06 UTC, Vladimir Panteleev wrote: On Friday, 3 March 2023 at 01:07:07 UTC, ryuukk_ wrote: I couldn't figure out dustmite, so i started from 0 and managed to hit something: https://github.com/ryuukk/dmd_bug ``Assertion failed: array index out of bounds, file game\app.d, line 5`` Wich indicates probably TLS problem? Yeah... `rt.a.stuffs` is a TLS variable. The D runtime manages TLS. `extern(C) main` bypasses D runtime initialization. I have some questions: 1. why does it work with LDC? 2. why does it work with DMD when build/link in 2 step? 3. why it doesn't work when DMD is invoked once for build/link 4. is this a bug in DMD or my code is wrong? 5. if it's wrong, then why does it compile/no error? ```sh #!/usr/bin/env bash set -e build_dmd() { echo "build dmd" dmd \ -debug -g \ -m64 -vcolumns -betterC -w -i -i=-std -i=-core \ -Igame \ -Istuff/ \ stuff/rt/object.d \ game/app.d \ -of=game.exe } build_ldc() { echo "build ldc" ldc2 \ -d-debug -g \ -m64 -vcolumns -betterC -w -i -i=-std -i=-core \ -Igame \ -Istuff/ \ stuff/rt/object.d \ game/app.d \ -of=game.exe } build_dmd_and_link() { echo "build dmd and link (2step)" dmd \ -debug -g -c \ -m64 -vcolumns -betterC -w -i -i=-std -i=-core \ -Igame \ -Istuff/ \ stuff/rt/object.d \ game/app.d \ -of=game.obj dmd \ -debug -g \ -m64 -vcolumns -betterC -w -i -i=-std -i=-core \ -Igame \ -Istuff/ \ game.obj \ -of=game.exe } build_ldc ./game.exe rm game.obj game.exe build_dmd_and_link ./game.exe rm game.obj game.exe build_dmd ./game.exe rm game.obj game.exe ```
Re: Bug in DMD?
On Friday, 3 March 2023 at 01:07:07 UTC, ryuukk_ wrote: I couldn't figure out dustmite, so i started from 0 and managed to hit something: https://github.com/ryuukk/dmd_bug ``Assertion failed: array index out of bounds, file game\app.d, line 5`` Wich indicates probably TLS problem? Yeah... `rt.a.stuffs` is a TLS variable. The D runtime manages TLS. `extern(C) main` bypasses D runtime initialization.
Re: Bug in DMD?
I couldn't figure out dustmite, so i started from 0 and managed to hit something: https://github.com/ryuukk/dmd_bug ``Assertion failed: array index out of bounds, file game\app.d, line 5`` Wich indicates probably TLS problem? This now reminds me of: https://issues.dlang.org/show_bug.cgi?id=23310 I am clueless what to do next, but at least now there is a small repro available for knowledgeable people
Re: Bug in DMD?
On 03/03/2023 10:38 AM, ryuukk_ wrote: On Thursday, 2 March 2023 at 21:21:14 UTC, Richard (Rikki) Andrew Cattermole wrote: There isn't anything we can do without source. But here is what I would do in this situation: 1. Look at the assembly at the point of debug break, from here it should give you hints as to why its trying to write to dawn.assets.Resource init array. 2. Dustmite, so we have something we can work with. I have no idea what does 1. mean, as for 2. do you have a link for a guide how to setup "dustmite"? When debugging, native debuggers i.e. Visual Studio, will provide you with the disassembly of the function currently being executed. Between this and other entries in the call stack, you can generally figure out what the statement is being executed just by looking at things like call instructions. The symbols there will be accurate.
Re: Bug in DMD?
On 3/2/23 15:34, ryuukk_ wrote: > the problem is not that it can run in the background, the problem is > figuring out > > 1. how to install > 2. how to setup > 3. how to run I haven't used it myself but dustmite seems to be integrated into dub. 'dub dustmite <...>' Ali
Re: Bug in DMD?
On 03/03/2023 12:34 PM, ryuukk_ wrote: 1. how to install Already is. Comes with dmd and ldc. You can also just do ``$ dub run digger -- args``. 2. how to setup > 3. how to run It is a bit of a pain but the basics is you need some sort of compilation command, list of sources and a test to confirm if it still fails. https://github.com/CyberShadow/DustMite/wiki#how-to-use-it
Re: Bug in DMD?
On Thursday, 2 March 2023 at 22:24:11 UTC, H. S. Teoh wrote: On Thu, Mar 02, 2023 at 09:55:55PM +, ryuukk_ via Digitalmars-d-learn wrote: On Thursday, 2 March 2023 at 21:38:23 UTC, ryuukk_ wrote: > On Thursday, 2 March 2023 at 21:21:14 UTC, Richard (Rikki) > Andrew > Cattermole wrote: [...] > > 2. Dustmite, so we have something we can work with. > > [...] 2. do you have a link for a guide how to setup > "dustmite"? https://dlang.org/blog/2020/04/13/dustmite-the-general-purpose-data-reduction-tool/ Dustmite automatically reduces your code to a minimal example that still exhibits the same problem, good for bug reports that are easily reproducible. Also useful if you don't want to publicly share the code for whatever reason, but still want to provide enough information so that the dmd devs can find the problem and fix it. [...] That's is not something i like doing, it should just work, i shouldn't have to debug DMD, that aint my job Dustmite can run in the background on a temporary copy of your code, you don't have to babysit it and can work on other things while it's doing its thing. T the problem is not that it can run in the background, the problem is figuring out 1. how to install 2. how to setup 3. how to run i was initially working on my game, i shouldn't have to take a 1 week break to debug dmd
Re: Bug in DMD?
On Thu, Mar 02, 2023 at 09:55:55PM +, ryuukk_ via Digitalmars-d-learn wrote: > On Thursday, 2 March 2023 at 21:38:23 UTC, ryuukk_ wrote: > > On Thursday, 2 March 2023 at 21:21:14 UTC, Richard (Rikki) Andrew > > Cattermole wrote: [...] > > > 2. Dustmite, so we have something we can work with. > > > > [...] 2. do you have a link for a guide how to setup "dustmite"? https://dlang.org/blog/2020/04/13/dustmite-the-general-purpose-data-reduction-tool/ Dustmite automatically reduces your code to a minimal example that still exhibits the same problem, good for bug reports that are easily reproducible. Also useful if you don't want to publicly share the code for whatever reason, but still want to provide enough information so that the dmd devs can find the problem and fix it. [...] > That's is not something i like doing, it should just work, i shouldn't > have to debug DMD, that aint my job Dustmite can run in the background on a temporary copy of your code, you don't have to babysit it and can work on other things while it's doing its thing. T -- Written on the window of a clothing store: No shirt, no shoes, no service.
Re: Bug in DMD?
On Thursday, 2 March 2023 at 21:38:23 UTC, ryuukk_ wrote: On Thursday, 2 March 2023 at 21:21:14 UTC, Richard (Rikki) Andrew Cattermole wrote: There isn't anything we can do without source. But here is what I would do in this situation: 1. Look at the assembly at the point of debug break, from here it should give you hints as to why its trying to write to dawn.assets.Resource init array. 2. Dustmite, so we have something we can work with. I have no idea what does 1. mean, as for 2. do you have a link for a guide how to setup "dustmite"? Better, can i send you a zip of my project? i'm not sure i'm willing to waste any more time trying to figure out what is wrong That's is not something i like doing, it should just work, i shouldn't have to debug DMD, that aint my job
Re: Bug in DMD?
On Thursday, 2 March 2023 at 21:21:14 UTC, Richard (Rikki) Andrew Cattermole wrote: There isn't anything we can do without source. But here is what I would do in this situation: 1. Look at the assembly at the point of debug break, from here it should give you hints as to why its trying to write to dawn.assets.Resource init array. 2. Dustmite, so we have something we can work with. I have no idea what does 1. mean, as for 2. do you have a link for a guide how to setup "dustmite"?
Re: Bug in DMD?
There isn't anything we can do without source. But here is what I would do in this situation: 1. Look at the assembly at the point of debug break, from here it should give you hints as to why its trying to write to dawn.assets.Resource init array. 2. Dustmite, so we have something we can work with.
Re: Bug in DMD?
It crashes with a weird message, address doesn't match the mangled name: ``C:\dev\kdom\projects\dawn\gl\glad\loader.d`` inside: ``module dawn.gl.glad.loader;`` ![screenshot](https://i.imgur.com/sY2KcgR.png)
Bug in DMD?
Hello, I encountered a weird issue, my program segfault when i feed DMD with my files and static libs It doesn't when i compile with LDC If i split the compile/link in 2 different steps, then all works correctly DMD (1step: ⛔): https://gist.github.com/ryuukk/f0ae2ae0c8980219c04d0c6d8678940d LDC (1step: ✅): https://gist.github.com/ryuukk/4c7706697583431389d5e2074548f7c4 DMD (2step: ✅): https://gist.github.com/ryuukk/a0373339e590ecdae91e3f05b2d81bf4 Looks like DMD is messing things up when mixing code with static libraries? Toolchains: - DMD32 D Compiler v2.102.1 - LDC - the LLVM D compiler (1.32.0-beta1):
Re: Bug or feature? iota has different semantics for integer and float arguments
On Saturday, 7 January 2023 at 02:31:14 UTC, Ali Çehreli wrote: On 1/6/23 17:50, Arredondo wrote: > Would anyone volunteer to file a bug report? Me! Me! :) https://issues.dlang.org/show_bug.cgi?id=23604 Ali Thanks a lot :D Arredondo.
Re: Bug or feature? iota has different semantics for integer and float arguments
On 1/6/23 17:50, Arredondo wrote: > Would anyone volunteer to file a bug report? Me! Me! :) https://issues.dlang.org/show_bug.cgi?id=23604 Ali
Re: Bug or feature? iota has different semantics for integer and float arguments
On Saturday, 7 January 2023 at 00:52:20 UTC, Ali Çehreli wrote: Although that difference is a bug, iota does have a special floating point implementation to prevent the accumulation of floating point errors. Thank you for this clarification Ali. I appreciate the fact that there is a specialized implementation for float types in an attempt to mitigate error accumulation. After posting my previous message I became convinced that the behavior I was seeing was indeed a bug. The specialized fp implementation simply does not conform to the semantics specified in the documentation: "If begin < end && step < 0 or begin > end && step > 0 or begin == end, then an empty range is returned." The culprit is this assert in the `in` block of the fp implementation: ``` assert((end - begin) / step >= 0, "iota: incorrect startup parameters"); ``` This effectively prevents iota from ever returning an empty range. Git blame points to a commit from March 2015. It's unbelievable to me this hasn't been fixed in almost 8 years. Would anyone volunteer to file a bug report? I attempted to do it myself but I would need to create an account in the Issue Tracking System, and apparently it doesn't accept gmail addresses anymore? (facepalm). Arredondo.
Re: Bug or feature? iota has different semantics for integer and float arguments
On 1/6/23 15:23, Arredondo wrote: > then you get an exception (incorrect startup parameters). Although that difference is a bug, iota does have a special floating point implementation to prevent the accumulation of floating point errors. I mention it as item 4 here: https://www.youtube.com/watch?v=gwUcngTmKhg=634s Briefly, iota's regular popFront() is a trivial front += step but it is ++n for floating types so that front can be begin + (n * step) for them. The iota discussion starts at an earlier point in the video here: https://www.youtube.com/watch?v=gwUcngTmKhg=558s Ali
Bug or feature? iota has different semantics for integer and float arguments
Consider: ``` import std.range.iota; auto r = iota(5, 0); ``` `r` is an empty range, as it should be. But if you call: ``` auto r = iota(5.0, 0); ``` then you get an exception (incorrect startup parameters). This was unexpected, and a pain to debug. What is the rationale behind iota having different semantics depending on whether the arguments are floats or not? Arredondo.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven wrote: Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something. The state of the memory can not be guaranteed by the compiler. That is the responsibility of the programmer. When a pointer gets over-written the memory it was pointing to remains owne by the program. It could be accesible by recovering the pointer. If you want to destroy the memory there are various ways of doing this depending on your performance needs. D has an optional garbage collector by default.
Re: Unique!struct bug - Re: unique_ptr | Unique for autoclose handle
On Thursday, 15 December 2022 at 20:12:12 UTC, Ali Çehreli wrote: I think this is a bug because the documentation clearly talks about destroying the object: OK: https://github.com/dlang/phobos/pull/8651 > do we need to do some kind of deprecation? The behavior is so different from the intention that I don't think anybody is using Unique anyway. :o) Yes, at least for structs.
Re: Unique!struct bug - Re: unique_ptr | Unique for autoclose handle
On 12/15/22 11:31, Nick Treleaven wrote: > On Wednesday, 14 December 2022 at 17:41:07 UTC, Ali Çehreli wrote: >> I've never used Unique but I think it has a bug (or a design issue?): >> Its destructor is the following: >> >> ~this() >> { >> if (_p !is null) >> { >> destroy(_p); >> _p = null; >> } >> } >> >> Because _p is a pointer, destroy(_p) will not dereference and destroy >> what it points to. I think this is a bug with Unique. I think it >> should do >> >> destroy(*_p); > > Now filed: > https://issues.dlang.org/show_bug.cgi?id=23561 Thanks. I was hoping others more experienced with Phobos implementation chime in. But to me, the intention is to destroy the object. One never wants to destroy a pointer as there is no operation there. As a minor proud moment, I do cover this issue: http://ddili.org/ders/d.en/memory.html#ix_memory.destroy > Do you think it's OK to just fix this or I think this is a bug because the documentation clearly talks about destroying the object: https://dlang.org/library/std/typecons/unique.html "When a Unique!T goes out of scope it will call destroy on the resource T that it manages, unless it is transferred. One important consequence of destroy is that it will call the destructor of the resource T." > do we need to do some kind of deprecation? The behavior is so different from the intention that I don't think anybody is using Unique anyway. :o) Ali
Re: pointer escaping return scope bug?
On Thursday, 15 December 2022 at 20:02:38 UTC, Nick Treleaven wrote: auto f() return @trusted => p ? p : v.ptr; Whoops, that can't be @trusted unless I `assert(p)`.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:24:33 UTC, Dukc wrote: On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven wrote: OK, so how do I make `lf` implicitly scope? Have the `int*` inside it to point to a local, or assign another `scope int*` to it. Thanks, this works: ```d @safe: struct S { int* p; int[0] v; // dummy storage auto f() return @trusted => p ? p : v.ptr; } void main() { int* p; { S s = S(new int); p = s.f; // error } } ```
Unique!struct bug - Re: unique_ptr | Unique for autoclose handle
On Wednesday, 14 December 2022 at 17:41:07 UTC, Ali Çehreli wrote: I've never used Unique but I think it has a bug (or a design issue?): Its destructor is the following: ~this() { if (_p !is null) { destroy(_p); _p = null; } } Because _p is a pointer, destroy(_p) will not dereference and destroy what it points to. I think this is a bug with Unique. I think it should do destroy(*_p); Now filed: https://issues.dlang.org/show_bug.cgi?id=23561 Do you think it's OK to just fix this or do we need to do some kind of deprecation?
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 15:03:57 UTC, ShadoLight wrote: I don't grok how `lf` can survive the local scope. Or am I missing something? Perhaps because the local scope is not pushed as a separate (anonymous) function on the stack... if true then, yes, then `lf` will indeed have the same physical lifetime as main (and `p`)...? On the other hand, if you add a destructor to `LockedFile`, it will be invoked at the end of the local scope, not the end of main. Yes, the actual code does have a destructor. It's analogous to this: ```d @safe: struct S { private int* fps; auto fp() return scope => fps; this(int) { fps = new int; } @disable this(); @disable void opAssign(S); ~this() @trusted // how do we make this safe? { import core.memory; GC.free(fps); } } void main() { int* p; { auto lf = S(5); p = lf.fp; } assert(p != null); // address escaped } ``` That compiles with -dip1000. D doesn't seem to have a way to prevent the memory outliving the struct. Just to note there is another problem when the struct is destroyed explicitly whilst the `fp` result is still live. But that could be solved by making `object.destroy` and `std.algorithm.move` be restricted to @system for certain structs like this one (either opt-in or some other mechanism). The first problem doesn't seem to have a solution.
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 17:45:57 UTC, Paul Backus wrote: On Friday, 25 November 2022 at 14:07:28 UTC, ShadoLight wrote: On Saturday, 19 November 2022 at 15:00:16 UTC, Paul Backus wrote: Since, in your example, `lf` has global lifetime, the compiler deduces that `lf.fp` also has global lifetime, and therefore there is nothing wrong with assigning it to `p`. I follow your rationale, but for the life of me I cannot see how `lf` _"has global lifetime"_. You're right, my terminology here is sloppy. I'm really talking about the memory pointed to by `lf`, not `lf` itself, so I should really say that `lf` *points to memory* with global lifetime (or perhaps "`*lf` has global lifetime"). Time to use separation logic #
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 14:07:28 UTC, ShadoLight wrote: On Saturday, 19 November 2022 at 15:00:16 UTC, Paul Backus wrote: Since, in your example, `lf` has global lifetime, the compiler deduces that `lf.fp` also has global lifetime, and therefore there is nothing wrong with assigning it to `p`. I follow your rationale, but for the life of me I cannot see how `lf` _"has global lifetime"_. You're right, my terminology here is sloppy. I'm really talking about the memory pointed to by `lf`, not `lf` itself, so I should really say that `lf` *points to memory* with global lifetime (or perhaps "`*lf` has global lifetime").
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 14:07:28 UTC, ShadoLight wrote: On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` [snip] I don't grok how `lf` can survive the local scope. Or am I missing something? Perhaps because the local scope is not pushed as a separate (anonymous) function on the stack... if true then, yes, then `lf` will indeed have the same physical lifetime as main (and `p`)...? On the other hand, if you add a destructor to `LockedFile`, it will be invoked at the end of the local scope, not the end of main. I find it a bit confusing what the term "lifetime" should pertain to in the case of variables declared inside a local scope inside a function - destructor invocation or physical existence of the variable on the stack? But this has no bearing on the heap allocation and the lifetime of `p` in the example.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:00:16 UTC, Paul Backus wrote: On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven wrote: Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something. I think this is intended behavior, because you *do* get an error if you replace `new int` with a pointer to a stack variable; e.g., int local; auto lf = LockedFile(); The `return scope` qualifier on the method does *not* mean "the return value of this method is `scope`". It means "this method may return one of this object's pointers, but does not allow them to escape anywhere else." In other words, it lets the compiler determine that the return value of `lf.fp` has *the same* lifetime as `lf` itself. Since, in your example, `lf` has global lifetime, the compiler deduces that `lf.fp` also has global lifetime, and therefore there is nothing wrong with assigning it to `p`. I follow your rationale, but for the life of me I cannot see how `lf` _"has global lifetime"_. Looks to me like `lf` is a value instance of the `LockedFile` struct (so on the stack) in a local scope inside main. I fully agree that the above code is not problematic, but isn't that because `p` is declared outside this local scope, and the allocation that happens inside the local scope (in the `lf` constructor) is on the heap, so the allocation (now assigned to `p`) survives the end of the local scope (and the end of the life of `lf`) since it is `p` that has global lifetime? I don't grok how `lf` can survive the local scope. Or am I missing something?
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven wrote: On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote: That's essentially just a function that returns its pointer parameter. So the program boils down to this: ```D @safe: int* fp(return scope int* p) { return p; } void main() { int* p; { auto lf = new int; p = fp(lf); } assert(p != null); // address escaped } ``` Which is fine, as far as I can tell. `lf` is not `scope`. And when you pass it through `fp`, the result is still not `scope`. So escaping it is allowed. You do get an error when you make `lf` `scope` (explicitly or implicitly). So everything seems to be in order. OK, so how do I make `lf` implicitly scope? Have the `int*` inside it to point to a local, or assign another `scope int*` to it.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven wrote: OK, so how do I make `lf` implicitly scope? By explicit/implicit I just meant this: scope explicit = new int; int x; auto implicit = That's probably not helping with whatever you want to accomplish.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote: That's essentially just a function that returns its pointer parameter. So the program boils down to this: @safe: int* fp(return scope int* p) { return p; } void main() { int* p; { auto lf = new int; p = fp(lf); } assert(p != null); // address escaped } Which is fine, as far as I can tell. `lf` is not `scope`. And when you pass it through `fp`, the result is still not `scope`. So escaping it is allowed. You do get an error when you make `lf` `scope` (explicitly or implicitly). So everything seems to be in order. OK, so how do I make `lf` implicitly scope?
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven wrote: Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something. I think this is intended behavior, because you *do* get an error if you replace `new int` with a pointer to a stack variable; e.g., int local; auto lf = LockedFile(); The `return scope` qualifier on the method does *not* mean "the return value of this method is `scope`". It means "this method may return one of this object's pointers, but does not allow them to escape anywhere else." In other words, it lets the compiler determine that the return value of `lf.fp` has *the same* lifetime as `lf` itself. Since, in your example, `lf` has global lifetime, the compiler deduces that `lf.fp` also has global lifetime, and therefore there is nothing wrong with assigning it to `p`.
Re: pointer escaping return scope bug?
On 19.11.22 15:07, Nick Treleaven wrote: Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something. Let me rewrite `fp` as a static method. It's easier (for me) to understand what's going on that way: static int* fp(return scope ref LockedFile that) { return that.fps; } That's essentially just a function that returns its pointer parameter. So the program boils down to this: @safe: int* fp(return scope int* p) { return p; } void main() { int* p; { auto lf = new int; p = fp(lf); } assert(p != null); // address escaped } Which is fine, as far as I can tell. `lf` is not `scope`. And when you pass it through `fp`, the result is still not `scope`. So escaping it is allowed. You do get an error when you make `lf` `scope` (explicitly or implicitly). So everything seems to be in order.
pointer escaping return scope bug?
Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something.
Re: druntime thread (from foreach parallel?) cleanup bug
On Tuesday, 1 November 2022 at 19:49:47 UTC, mw wrote: On Tuesday, 1 November 2022 at 18:18:45 UTC, Steven Schveighoffer wrote: [...] Maybe the hunt library author doesn't know. (My code does not directly use this library, it got pulled in by some other decencies.) [...] Please, if you see anything in the docs that needs to be updated, make a PR right away <3 Documentation saves lives! The times I have thought "I'll do it later" have been too many.
Re: druntime thread (from foreach parallel?) cleanup bug
On Tuesday, 1 November 2022 at 18:18:45 UTC, Steven Schveighoffer wrote: Oh yeah, isDaemon detaches the thread from the GC. Don't do that unless you know what you are doing. As discussed on discord, this isn't actually true. All it does is prevent the thread from being joined before exiting the runtime. What is *likely* happening is, the runtime shuts down. That thread is still running, but the D runtime is gone. So it eventually starts trying to do something (like let's say, access thread local storage), and it's gone. Hence the segfault. -Steve
Re: druntime thread (from foreach parallel?) cleanup bug
On Tuesday, 1 November 2022 at 18:18:45 UTC, Steven Schveighoffer wrote: And I just noticed, one of the thread trace points to here: https://github.com/huntlabs/hunt/blob/master/source/hunt/util/DateTime.d#L430 ``` class DateTime { shared static this() { ... dateThread.isDaemon = true; // not sure if this is related } } ``` in the comments, it said: "BUG: ... crashed". Looks like someone run into this (cleanup) issue already, but unable to fix it. Anyway I logged an issue there: https://github.com/huntlabs/hunt/issues/96 Oh yeah, isDaemon detaches the thread from the GC. Don't do that unless you know what you are doing. Maybe the hunt library author doesn't know. (My code does not directly use this library, it got pulled in by some other decencies.) Currently, the `isDaemon` doc does not mention this about this: https://dlang.org/library/core/thread/threadbase/thread_base.is_daemon.html Sets the daemon status for this thread. While the runtime will wait for all normal threads to complete before tearing down the process, daemon threads are effectively ignored and thus will not prevent the process from terminating. In effect, daemon threads will be terminated automatically by the OS when the process exits. Maybe we should add to the doc? BTW, what is exactly going wrong with their code? I saw the tick() method call inside the anonymous `dateThread` is accessing these two stack variables of shared static this(): https://github.com/huntlabs/hunt/blob/master/source/hunt/util/DateTime.d#L409 Appender!(char[])[2] bufs; const(char)[][2] targets; Why does this tick() call work after the static this() finished in a normal run? Why the problem only shows up when program finish?
Re: druntime thread (from foreach parallel?) cleanup bug
On Tuesday, 1 November 2022 at 18:18:45 UTC, Steven Schveighoffer wrote: Oh yeah, isDaemon detaches the thread from the GC. Don't do that unless you know what you are doing. As discussed on discord, this isn't true actually. All it does is prevent the thread from being joined before exiting the runtime. What is *likely* happening is, the runtime shuts down. That thread is still running, but the D runtime is gone. So it eventually starts trying to do something (like let's say, access thread local storage), and it's gone. Hence the segfault. -Steve
Re: druntime thread (from foreach parallel?) cleanup bug
On 11/1/22 1:47 PM, mw wrote: Can you show a code snippet that includes the parallel foreach? (It's just a very straight forward foreach on an array; as I said it may not be relevant.) And I just noticed, one of the thread trace points to here: https://github.com/huntlabs/hunt/blob/master/source/hunt/util/DateTime.d#L430 ``` class DateTime { shared static this() { ... dateThread.isDaemon = true; // not sure if this is related } } ``` in the comments, it said: "BUG: ... crashed". Looks like someone run into this (cleanup) issue already, but unable to fix it. Anyway I logged an issue there: https://github.com/huntlabs/hunt/issues/96 Oh yeah, isDaemon detaches the thread from the GC. Don't do that unless you know what you are doing. -Steve
Re: druntime thread (from foreach parallel?) cleanup bug
Can you show a code snippet that includes the parallel foreach? (It's just a very straight forward foreach on an array; as I said it may not be relevant.) And I just noticed, one of the thread trace points to here: https://github.com/huntlabs/hunt/blob/master/source/hunt/util/DateTime.d#L430 ``` class DateTime { shared static this() { ... dateThread.isDaemon = true; // not sure if this is related } } ``` in the comments, it said: "BUG: ... crashed". Looks like someone run into this (cleanup) issue already, but unable to fix it. Anyway I logged an issue there: https://github.com/huntlabs/hunt/issues/96
Re: druntime thread (from foreach parallel?) cleanup bug
On Tue, Nov 01, 2022 at 10:37:57AM -0700, Ali Çehreli via Digitalmars-d-learn wrote: > On 11/1/22 10:27, H. S. Teoh wrote: > > > Maybe try running Digger to reduce the code for you? > > Did you mean dustmite, which is accessible as 'dub dustmite > ' but I haven't used it. Oh yes, sorry, I meant dustmite, not digger. :-P > My guess for the segmentation fault is that the OP is executing > destructor code that assumes some members are alive. If so, the code > should be moved from destructors to functions to be called like > obj.close(). But it's just a guess... [...] Yes, that's a common gotcha. T -- We are in class, we are supposed to be learning, we have a teacher... Is it too much that I expect him to teach me??? -- RL
Re: druntime thread (from foreach parallel?) cleanup bug
On 11/1/22 10:27, H. S. Teoh wrote: > Maybe try running Digger to reduce the code for you? Did you mean dustmite, which is accessible as 'dub dustmite ' but I haven't used it. My guess for the segmentation fault is that the OP is executing destructor code that assumes some members are alive. If so, the code should be moved from destructors to functions to be called like obj.close(). But it's just a guess... Ali
Re: druntime thread (from foreach parallel?) cleanup bug
On Tue, Nov 01, 2022 at 05:19:56PM +, mw via Digitalmars-d-learn wrote: > My program received signal SIGSEGV, Segmentation fault. > > Its simplified structure looks like this: > > ``` > void foo() { > ... > writeln("done"); // saw this got printed! > } > > int main() { > foo(); > return 0; > } > > ``` Can you show a code snippet that includes the parallel foreach? Because the above code snippet is over-simplified to the point it's impossible to tell what the original problem might be, since obviously calling a function that calls writeln would not crash the program. Maybe try running Digger to reduce the code for you? T -- Never step over a puddle, always step around it. Chances are that whatever made it is still dripping.
druntime thread (from foreach parallel?) cleanup bug
My program received signal SIGSEGV, Segmentation fault. Its simplified structure looks like this: ``` void foo() { ... writeln("done"); // saw this got printed! } int main() { foo(); return 0; } ``` So, just before the program exit, it failed. I suspect druntime has a thread (maybe due to foreach parallel) cleanup bug somewhere, which is unrelated to my own code. This kind of bug is hard to re-produce, not sure if I should file an issue. I'm using: LDC - the LLVM D compiler (1.30.0) on x86_64. Under gdb, here is the threads info (for the record): Thread 11 "xxx" received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x153df700 (LWP 36258)] __GI___res_iclose (free_addr=true, statp=0x153dfdb8) at res-close.c:103 103 res-close.c: No such file or directory. (gdb) info threads Id Target Id Frame 1Thread 0x15515000 (LWP 36244) "lt" 0x10af1d2d in __GI___pthread_timedjoin_ex (threadid=23456246527744, thread_return=0x0, abstime=0x0, block=) at pthread_join_common.c:89 * 11 Thread 0x153df700 (LWP 36258) "lt" __GI___res_iclose (free_addr=true, statp=0x153dfdb8) at res-close.c:103 17 Thread 0x155544817700 (LWP 36264) "lt" 0x10afac70 in __GI___nanosleep (requested_time=0x155544810e90, remaining=0x155544810ea8) at ../sysdeps/unix/sysv/linux/nanosleep.c:28 (gdb) thread 1 [Switching to thread 1 (Thread 0x15515000 (LWP 36244))] #0 0x10af1d2d in __GI___pthread_timedjoin_ex (threadid=23456246527744, thread_return=0x0, abstime=0x0, block=) at pthread_join_common.c:89 89 pthread_join_common.c: No such file or directory. (gdb) where #0 0x10af1d2d in __GI___pthread_timedjoin_ex (threadid=23456246527744, thread_return=0x0, abstime=0x0, block=) at pthread_join_common.c:89 #1 0x55fb94f8 in core.thread.osthread.joinLowLevelThread(ulong) () #2 0x55fd7210 in _D4core8internal2gc4impl12conservativeQw3Gcx15stopScanThreadsMFNbZv () #3 0x55fd3ae7 in _D4core8internal2gc4impl12conservativeQw3Gcx4DtorMFZv () #4 0x55fd3962 in _D4core8internal2gc4impl12conservativeQw14ConservativeGC6__dtorMFZv () #5 0x55fc2ce7 in rt_finalize2 () #6 0x55fc0056 in rt_term () #7 0x55fc0471 in _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv () #8 0x55fc0356 in _d_run_main2 () #9 0x55fc01ae in _d_run_main () #10 0x55840c02 in main (argc=2, argv=0x7fffe188) at //home/zhou/project/ldc2-1.30.0-linux-x86_64/bin/../import/core/internal/entrypoint.d:42 #11 0x10163b97 in __libc_start_main (main=0x55840be0 , argc=2, argv=0x7fffe188, init=, fini=, rtld_fini=, stack_end=0x7fffe178) at ../csu/libc-start.c:310 #12 0x556dccca in _start () (gdb) thread 11 [Switching to thread 11 (Thread 0x153df700 (LWP 36258))] #0 __GI___res_iclose (free_addr=true, statp=0x153dfdb8) at res-close.c:103 103 res-close.c: No such file or directory. (gdb) where #0 __GI___res_iclose (free_addr=true, statp=0x153dfdb8) at res-close.c:103 #1 res_thread_freeres () at res-close.c:138 #2 0x102de8c2 in __libc_thread_freeres () at thread-freeres.c:29 #3 0x10af0700 in start_thread (arg=0x153df700) at pthread_create.c:476 #4 0x10263a3f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (gdb) thread 17 [Switching to thread 17 (Thread 0x155544817700 (LWP 36264))] #0 0x10afac70 in __GI___nanosleep (requested_time=0x155544810e90, remaining=0x155544810ea8) at ../sysdeps/unix/sysv/linux/nanosleep.c:28 28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory. (gdb) where #0 0x10afac70 in __GI___nanosleep (requested_time=0x155544810e90, remaining=0x155544810ea8) at ../sysdeps/unix/sysv/linux/nanosleep.c:28 #1 0x55fb8c3b in _D4core6thread8osthread6Thread5sleepFNbNiSQBo4time8DurationZv () #2 0x55d9a0c2 in _D4hunt4util8DateTimeQj25_sharedStaticCtor_L406_C5FZ9__lambda4MFZv () at home/zhou/.dub/packages/hunt-1.7.16/hunt/source/hunt/util/DateTime.d:430 #3 0x55fb89f4 in thread_entryPoint () #4 0x10af06db in start_thread (arg=0x155544817700) at pthread_create.c:463 #5 0x10263a3f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Re: Is this a new bug ?
On Saturday, 24 September 2022 at 06:13:55 UTC, test123 wrote: If so please report it for me to bugs platform. I can not register one. ```d package { version(TEST) { static: } else { __gshared: } uint test = 0; } ``` ldmd2 -betterC -vtls -c ./test.d ./test.d(7): `test` is thread local static does nothing to module level variables. Without attributes, test will be thread local. Your attributes are having no effect on the variable because they don’t apply outside the braces. -Steve
Re: Is this a new bug ?
On Saturday, 24 September 2022 at 06:13:55 UTC, test123 wrote: If so please report it for me to bugs platform. This isn't a bug, the effect of keyword: things stop at the matching }. (static if and version don't introduce a namespace scope, but they still follow this rule for the { colon: ... } blocks) You need to duplicate your uint test2 variable inside those branches.
Re: Is this a new bug ?
On Saturday, 24 September 2022 at 07:11:12 UTC, rikki cattermole wrote: ```d version(all) { __gshared: uint test2; } uint test; ``` Output with -vtls: ``` Up to 2.079.1: Success with output: onlineapp.d(9): test is thread local Since 2.080.1: Success with output: onlineapp.d(9): `test` is thread local ``` Looks fine to me. I think it should not be thread local.
Re: Is this a new bug ?
```d version(all) { __gshared: uint test2; } uint test; ``` Output with -vtls: ``` Up to 2.079.1: Success with output: onlineapp.d(9): test is thread local Since 2.080.1: Success with output: onlineapp.d(9): `test` is thread local ``` Looks fine to me.
Is this a new bug ?
If so please report it for me to bugs platform. I can not register one. ```d package { version(TEST) { static: } else { __gshared: } uint test = 0; } ``` ldmd2 -betterC -vtls -c ./test.d ./test.d(7): `test` is thread local
Re: How to workaround on this (bug?)
Provide two functions and let the caller choose ``` void fun(ref Variant v) nothrow { } void fun2(Variant v) { fun(v); } ```
Re: How to workaround on this (bug?)
On Friday, 16 September 2022 at 22:43:43 UTC, frame wrote: ```d import std.variant; // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow` void fun(Variant v) nothrow { } void main() { fun(Variant()); } ``` A reference, pointer or slice works. I could do something on the caller site but the signature of `fun()` should remain like above. A reference effectively is a never-`null` pointer. A slice is a pointer to the first of many objects plus the number of those objects (or empty, or `null`). It boils down to pointers, and the pointed-to `Variant` object is not the responsibility of `fun`. When you have a parameter that binds by copy, you cannot escape from calling its destructor, and if one happens not to be `nothrow`, your function cannot be `nothrow`. The new semantics for `in` (compile with `-preview=in`) might work for you. The `in` storage class binds by copy if the copy is cheap – which I suspect is never the case for a `Variant` – or else by reference; and it can bind temporaries by reference (unlike `ref`). However, `in` also incurs `const` and `scope`. It is unlikely that `scope` will be your problem, but `const` very well might be an issue when the contained value has indirections to mutable values, e.g. an `int[]` will be read as a `const(int)[]`. Calling the destructor is then the responsibility of the caller. ```d // Compile with -preview=in import std.variant; void fun(in Variant v) nothrow { } void main() { fun(Variant()); // okay: `in` binds rvalues Variant v; fun(v); // okay: `in` binds lvalues } ```
Re: How to workaround on this (bug?)
On Sat, Sep 17, 2022 at 12:19:16AM +, frame via Digitalmars-d-learn wrote: > On Friday, 16 September 2022 at 23:06:35 UTC, H. S. Teoh wrote: > > > Basically, if you pass something to .fun by value, then that value > > must be destroyed by .fun once it's ready to return. So if the > > value has a dtor, the dtor must be called upon exiting from .fun. > > Since Variant has a throwing dtor, this means .fun may throw when > > it's about to return, which violates `nothrow`. > > I understand why this happens but not why the compiler does not check > if the value is actually destroyed in user code by `.destroy()`. [...] I don't know for sure, but my guess is that .destroy is seen by the compiler just like any other D function; i.e., it's not treated specially. So it would not factor into the compiler's lifetime considerations. Or are you talking about the case where the Variant may not actually contain values that have dtors? That information is not available until runtime; the compiler can't make decisions based on that. T -- Political correctness: socially-sanctioned hypocrisy.
Re: How to workaround on this (bug?)
On Friday, 16 September 2022 at 23:06:35 UTC, H. S. Teoh wrote: Basically, if you pass something to .fun by value, then that value must be destroyed by .fun once it's ready to return. So if the value has a dtor, the dtor must be called upon exiting from .fun. Since Variant has a throwing dtor, this means .fun may throw when it's about to return, which violates `nothrow`. I understand why this happens but not why the compiler does not check if the value is actually destroyed in user code by `.destroy()`. Thanks for your suggestion, I will consider this.
Re: How to workaround on this (bug?)
On Fri, Sep 16, 2022 at 10:43:43PM +, frame via Digitalmars-d-learn wrote: > ```d > import std.variant; > > // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not > `nothrow` > void fun(Variant v) nothrow > { > > } > > void main() > { >fun(Variant()); > } > ``` > > A reference, pointer or slice works. Yes, because in that case the dtor would not need to be invoked in .fun. > I could do something on the caller site but the signature of `fun()` > should remain like above. I was doing to suggest using `const ref`, but if the signature must remain the same, then I'm out of ideas. Basically, if you pass something to .fun by value, then that value must be destroyed by .fun once it's ready to return. So if the value has a dtor, the dtor must be called upon exiting from .fun. Since Variant has a throwing dtor, this means .fun may throw when it's about to return, which violates `nothrow`. T -- If creativity is stifled by rigid discipline, then it is not true creativity.
How to workaround on this (bug?)
```d import std.variant; // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow` void fun(Variant v) nothrow { } void main() { fun(Variant()); } ``` A reference, pointer or slice works. I could do something on the caller site but the signature of `fun()` should remain like above.
Re: can not take const struct member address at CTFE , is this a bug?
On Thursday, 15 September 2022 at 11:33:43 UTC, Dennis wrote: On Thursday, 15 September 2022 at 04:13:56 UTC, test123 wrote: I hope we have github bugs. It's being worked on. glad to know we are move into github. Please help me create a bug report if who has free time and bugs account. Here you go: https://issues.dlang.org/show_bug.cgi?id=23336 thanks for the help.
Re: can not take const struct member address at CTFE , is this a bug?
On Thursday, 15 September 2022 at 04:13:56 UTC, test123 wrote: I hope we have github bugs. It's being worked on. Please help me create a bug report if who has free time and bugs account. Here you go: https://issues.dlang.org/show_bug.cgi?id=23336
Re: can not take const struct member address at CTFE , is this a bug?
On Wednesday, 14 September 2022 at 14:41:38 UTC, Steven Schveighoffer wrote: On 9/14/22 12:53 AM, test123 wrote: On Wednesday, 14 September 2022 at 00:40:38 UTC, Ruby The Roobster wrote: The addresses of items stored in memory are by definition not constant. This isn't a bug. If so why this can work ? ```d struct c { uint a, b;} __gshared const c d = { 3, 4}; __gshared const e = & d; ``` the `e` can get address of `d`, then it should be to get address of `d.a` Yes, this looks like a bug. Please report if not reported already. -Steve Thanks for explain. Some how I can not create account for d Bugs, I hope we have use github bugs. Please help me create a bug report if who has free time and bugs account.
Re: can not take const struct member address at CTFE , is this a bug?
On 9/14/22 12:53 AM, test123 wrote: On Wednesday, 14 September 2022 at 00:40:38 UTC, Ruby The Roobster wrote: The addresses of items stored in memory are by definition not constant. This isn't a bug. If so why this can work ? ```d struct c { uint a, b;} __gshared const c d = { 3, 4}; __gshared const e = & d; ``` the `e` can get address of `d`, then it should be to get address of `d.a` Yes, this looks like a bug. Please report if not reported already. -Steve
Re: can not take const struct member address at CTFE , is this a bug?
On Wednesday, 14 September 2022 at 00:40:38 UTC, Ruby The Roobster wrote: The addresses of items stored in memory are by definition not constant. This isn't a bug. If so why this can work ? ```d struct c { uint a, b;} __gshared const c d = { 3, 4}; __gshared const e = & d; ``` the `e` can get address of `d`, then it should be to get address of `d.a`
Re: can not take const struct member address at CTFE , is this a bug?
On Tuesday, 13 September 2022 at 11:16:55 UTC, test123 wrote: ```d struct c { uint a, b;} __gshared const c d = { 3, 4}; __gshared const e = ``` ./test.d(4): Error: expression `(3u, 4u).a` is not a constant I need this to work around C struct array member like this: ```c struct c { uint32_t a, b; uint32_t[] arr; } ``` If I can take const object member address as __gshared const, then the problem is fixed. Or if I can force cast the const object pointer into other type, will work be able to work this around. (but not work) ```sh Error: reinterpreting cast from `const(validate_KnownRegex_enum_init_type)*` to `const(upb_MiniTable_Enum)*` is not supported in CTFE ``` The addresses of items stored in memory are by definition not constant. This isn't a bug.
can not take const struct member address at CTFE , is this a bug?
```d struct c { uint a, b;} __gshared const c d = { 3, 4}; __gshared const e = ``` ./test.d(4): Error: expression `(3u, 4u).a` is not a constant I need this to work around C struct array member like this: ```c struct c { uint32_t a, b; uint32_t[] arr; } ``` If I can take const object member address as __gshared const, then the problem is fixed. Or if I can force cast the const object pointer into other type, will work be able to work this around. (but not work) ```sh Error: reinterpreting cast from `const(validate_KnownRegex_enum_init_type)*` to `const(upb_MiniTable_Enum)*` is not supported in CTFE ```
Re: mixin template bug with opBinary?
On Friday, 22 July 2022 at 12:33:37 UTC, Anthony Quizon wrote: I get: ``` foo.d(16): Error: mixin `foo.B.opBi!(B, ["+":function (B a, B b) pure nothrow @nogc @safe => a])` does not match template declaration `opBi(A, A function(A, A)[string] f0)` ``` Is this a bug or am I doing something wrong? Looks like this bug: https://issues.dlang.org/show_bug.cgi?id=22540
Re: mixin template bug with opBinary?
On Friday, 22 July 2022 at 12:56:44 UTC, Adam D Ruppe wrote: ``` mixin template opBi( alias f0 ) { static foreach (k, f; f0) { typeof(this) opBinary(string op: k)(typeof(this) r) { return f(this, r); } } } ``` Thanks, this seems to do the trick.
Re: mixin template bug with opBinary?
On 7/22/22 8:33 AM, Anthony Quizon wrote: Hello, I'm trying to create a mixin for quick binary operator overloads by passing in types with a corresponding associative array of strings to functions. However, the code I currently have: ``` module foo; mixin template opBi( A, A function(A, A)[string] f0, ) { static foreach (k, f; f0) { A opBinary(string op: k)(A r) { return f(this, r); } } } struct A { mixin opBi!( A, [ "+": (A a, A b) => a], ); } struct B { mixin opBi!( B, [ "+": (B a, B b) => a], ); } ``` Will not let me override operators on both struct A and B. I get: ``` foo.d(16): Error: mixin `foo.B.opBi!(B, ["+":function (B a, B b) pure nothrow @nogc @safe => a])` does not match template declaration `opBi(A, A function(A, A)[string] f0)` ``` Is this a bug or am I doing something wrong? It's typing the AA differently, and therefore it doesn't fit. The type of the AA you are passing in is `T1[string]`, where it's expecting `T2[string]`, where: `T1` is `B function(B, B) pure nothrow @nogc @safe` `T2` is `B function(B, B)` I don't know if there's a better way to do this, other than use a further template parameter to match the function type passed in. -Steve
Re: mixin template bug with opBinary?
On Friday, 22 July 2022 at 12:33:37 UTC, Anthony Quizon wrote: Is this a bug or am I doing something wrong? I think this is a bug. The compiler must not take well to this pattern, maybe the assoc array template argument, but idk. It looks like the first type used gets cached and reused even if it is supposed to change. I vaguely recall seeing this before but yeah smells buggy anyway. An alternative you might consider is dropping some of the type and using typeof(this): ``` module foo; mixin template opBi( alias f0 ) { static foreach (k, f; f0) { typeof(this) opBinary(string op: k)(typeof(this) r) { return f(this, r); } } } struct A { mixin opBi!( [ "+": (A a, A b) => a], ); } struct B { mixin opBi!( [ "+": (B a, B b) => a], ); } ``` That sidesteps the bug though it just trusts you pass the right type to `f0`.