Closed Kerollmops closed 4 years ago
I just hit the "used after freed" error and it did not comes from the RedisAlloc
type.
redis-server(31749,0x700005d85000) malloc: *** error for object 0x101900e80: pointer being freed was not allocated
Process 31749 stopped
* thread #5, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100008c87 redis-server`dictSdsKeyCompare + 71
redis-server`dictSdsKeyCompare:
-> 0x100008c87 <+71>: movzbl -0x1(%rdx), %edi
0x100008c8b <+75>: movl %edi, %ecx
0x100008c8d <+77>: andb $0x7, %cl
0x100008c90 <+80>: xorl %eax, %eax
```
* thread #5, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x0000000100008c87 redis-server`dictSdsKeyCompare + 71
frame #1: 0x0000000100006a82 redis-server`dictAddRaw + 146
frame #2: 0x00000001000069b7 redis-server`dictAdd + 23
frame #3: 0x0000000100025bba redis-server`dbAdd + 42
frame #4: 0x0000000100025d9f redis-server`setKey + 63
frame #5: 0x000000010008ed2b redis-server`RM_StringSet + 75
frame #6: 0x0000000101e339b1 libspo2.dylib`redismodule::raw::string_set::h43380443db61ae94(key=0x0000000100600440, s=0x0000000101904ab0) at raw.rs:237:13
frame #7: 0x0000000101e3af5f libspo2.dylib`redismodule::key::RedisKeyWritable::write::h1837aa3bbfad52e1(self=0x0000000102900228, val=(data_ptr = "208 Already Reportedlate, gzip\r\n", length = 20)) at key.rs:149:14
frame #8: 0x0000000101a13a06 libspo2.dylib`spo2::health_checker::health_checker::_$u7b$$u7b$closure$u7d$$u7d$::h12785cbc7d0c1d66 at health_checker.rs:27:24
frame #9: 0x0000000101a163dd libspo2.dylib`_$LT$std..future..GenFuture$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$::poll::_$u7b$$u7b$closure$u7d$$u7d$::h2ba3aadc66258a96 at future.rs:42:38
frame #10: 0x0000000101a15938 libspo2.dylib`std::future::set_task_context::h78731454346506a0(cx=0x000070000577b6d0, f=closure-1 @ 0x000070000577b228) at future.rs:78:4
frame #11: 0x0000000101a161c2 libspo2.dylib`_$LT$std..future..GenFuture$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$::poll::h64c9a35070938477(self=Pin<&mut std::future::GenFuture
@Kerollmops thanks for the detailed report!
Regarding the use of a feature to enable the Redis allocator: That's a good idea; I'll look at it.
Regarding the use of the System
allocator fallback: Good point; I agree that it it should fall back to the Global allocator and not the system one.
Regarding the crash:
A while ago, I also encountered a crash related to the allocator. It seems similar, but I haven't dived into the details of your crash yet. It was related to the use of std::io
(via println!
) before switching the allocator to the Redis one; I guess there is something in the std::io
implementation that allocates an internal buffer or such that can be realloc
d at a later stage.
What I did to solve it is make sure that no std::io
calls were performed before switching the allocator. This was fixed by 2c37545 and 08d8fbc.
Does your crash still happen with current master
?
@Kerollmops Update: It seems like your version already included these commits, so that may not be the root cause.
Thank you for the reply,
I do not think it would be possible to fallback on the global allocator as it is RedisAlloc
once declared.
Notice that the crash is not related to the allocator in any way because I disabled it on my repository.
Due to the recent changes (#68) this is probably no longer relevant so I'm closing it. Please reopen if it is still relevant.
Currently the
RedisAlloc
is enforced at compilation and then at runtime a flag is used to enabled the allocator or not.The first problem is that if the application do not want to use it it is currently not possible as it is always enabled in the macro.
The second problem is that the global allocator is enforced and even if the
use_redis_alloc
function is not called the allocator will fallback on theSystem
allocator, therefore it is not possible to use, for example, the jemalloc one (which can be way more performant than the system's one).The third and last problem is that I faced
BAD_ACCESS
crashes that were triggered inside theRedisAlloc::dealloc
function of the kind: "pointer used after being freed". I think about it and it was probably because theUSE_REDIS_ALLOC
static was enabled after somealloc
calls were already made to the allocator and therefore allocations were made by the system's one but freed by the redis one.One solution could have been to enforce the allocator only when a specific feature is set and do not rely on a secondary runtime setting (i.e. the flag) to enable or disable the allocator, it is dangerous.
By the way I did not take the time to look at what does declaring a
global_allocator
do in a library, wasn't it made to be used in a binary project? What happen if I declare anotherglobal_allocator
inside mymain.rs
file?