-
-
Notifications
You must be signed in to change notification settings - Fork 422
[RFC] Add pure fail-fast assertMalloc, assertCalloc, assertRealloc #2276
Conversation
|
Thanks for your pull request, @n8sh! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + druntime#2276" |
9ee729c
to
fc9c777
Compare
src/core/memory.d
Outdated
| void* ret = fakePureMalloc(size); | ||
| if (!ret && size) | ||
| { | ||
| version (D_BetterC) assert(0, "Memory allocation failed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WalterBright has made the decision that we should be using assert(0) (preferably assert(false)) for both -betterC and non-betterC builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also it would be better to use version (D_Exceptions) to check whether exceptions can be thrown as LDC/GDC allow to disable them selectively (and e.g. WebAssembly might not defined -betterC, but still not support exceptions.)
|
|
||
| @nogc nothrow pure @system unittest | ||
| { | ||
| const int errno = fakePureErrno(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fakePureErrno is mangled to fakePureErrnoImpl which is not a template. Therefore this won't work until fakePureErrnoImpl is made into a template, or some other solution is devised.
Edit: I mean it won't work in -betterC until fakePureErrnoImpl is made into a template, or some other solution is devised
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be fixed now.
| * The functions may terminate the program using `onOutOfMemoryError` or | ||
| * `assert(0)`. These functions' purity guarantees no longer hold if | ||
| * the program continues execution after catching AssertError or | ||
| * OutOfMemoryError. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this comment needs updating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept the mention of the possibility so if we later change to using onOutOfMemoryError no one will be blindsided. Do you think it's better to remove it because that's too unlikely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to change anything immediately, IMO. We can wait to see how the review goes. It just eventually needs to reflect the final implementation.
45fa62e
to
fe1119f
Compare
src/core/memory.d
Outdated
|
|
||
| version (D_BetterC) @nogc nothrow private @system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this implementation work in non-betterC builds? Can't we use this implementation for both -betterC and non-betterC builds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would work. The purpose of the version branch is so outside code that assumes fakePureErroImpl exists and tries to link to it will not break.
|
I would argue that OOM is not a logical error on the programmer side, rather it is an exception from the program environment, albeit a non-recoverable from one. IMO, we should continue calling P.S. Thanks a lot for working on this guys, I would prefer to do the work myself instead of just talking, but sadly I have very limited free time these days. |
|
@ZombineDev That makes sense. |
Also change pureMalloc etc. to templates so they work in betterC.
I'm not terribly partial to either one, but @WalterBright has spoken. We need to come to some consensus about this and apply it consistently. Edit: I will add that it'd be kind of nice if both -betterC and non-betterC behaved the same whenever possible. |
|
Sorry! Wrong button. |
I took your summary to mean that he was okay with using assert but not that he was mandating it. Did I get the wrong idea?
|
@WalterBright will have to speak for himself, but my interpretation is that he preferred us to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm OK with this, but the DDoc comments still need updating.
|
We still need to come to some consensus about |
| return ret; | ||
| } | ||
| /// ditto | ||
| void* assertRealloc()(void* ptr, size_t size) @nogc nothrow pure @system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since realloc() free's memory, it cannot ever be considered pure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also already a pureRealloc.
Lines 840 to 847 in db2910e
| /// ditto | |
| void* pureRealloc(void* ptr, size_t size) @system pure @nogc nothrow | |
| { | |
| const errnosave = fakePureErrno(); | |
| void* ret = fakePureRealloc(ptr, size); | |
| fakePureErrno() = errnosave; | |
| return ret; | |
| } |
These functions achieve purity by aborting the program on failure so errno is never observed to change. This PR also changes
pureMallocetc. to templates so they work in betterC.The idea was suggested by @ZombineDev at dlang/phobos#6660 (comment) and #2268 (comment). The sole difference is that instead of adding a boolean template parameter to
pureMallocI instead named the new variant differently. I felt thatassertMalloc(100)has a more obvious meaning thanpureMalloc!true(100)which gives no hint as to whether it's the one that aborts on failure or the one that saves and restores errno.