leif
2017-8-24 17:57:55

@mflatt If I have a native library that uses pthreads, lets the user set a callback, the callback goes to a Racket function, and the native library calls that callback from another thread, would that likely cause the Racket VM to segfault?


mflatt
2017-8-24 18:00:04

@leif Yes. See #:async-apply for the way to solve that problem.


leif
2017-8-24 18:01:57

Ah, okay, that would explain a lot.


leif
2017-8-24 18:03:11

So that looks like its just a short function which is supposed to run quickly


leif
2017-8-24 18:03:26

That you can use to say, add something to a datastructure the main thread grabs.


leif
2017-8-24 18:03:36

At least that’s what it looks like to mel


leif
2017-8-24 18:03:37

me*


leif
2017-8-24 18:04:22

Would I put that on the callback _fun type, or the function where I set the _fun?


mflatt
2017-8-24 18:05:03

It’s a property of the callback


leif
2017-8-24 18:06:57

That makes sense, so in the case of: (define-libvid set-racket-log-callback (_fun (_fun _pointer _int _string -> _void) -> _void)) It would go on the inner callback.


leif
2017-8-24 18:11:50

Or not, as this doesn’t seem to even print out ‘here’: (define-libvid set-racket-log-callback (_fun (_fun #:async-apply (λ (th) (displayln "here") (th)) _pointer _int _string -> _void) -> _void))


leif
2017-8-24 18:11:57

so I’m going to look for examples.


leif
2017-8-24 18:13:10

Oh interesting, the only examples I see use it as a box.


mflatt
2017-8-24 18:15:47

There are non-box examples in “net/osx-ssl.rkt”


leif
2017-8-24 18:21:39

Hmm…that looks like what I was doing. Is it possible for the GC to collect a closure defined at the the module level?


leif
2017-8-24 18:21:50

(define and exported and immutable)


leif
2017-8-24 18:22:16

well, defined and exported and not set!ed anyway.


samth
2017-8-24 18:23:00

no


samth
2017-8-24 18:23:17

unless the whole module instance is collected, which is unlikely


leif
2017-8-24 18:24:02

Ya, that’s what I thought. Oh well. :disappointed:


leif
2017-8-24 18:41:11

Ahhh…I’m not setting the keep flag propertly


leif
2017-8-24 18:41:12

properly*


leif
2017-8-24 18:42:24

BTW @mflatt the docs say: “…not suitable for a function used multiple times as a reatined callback”


leif
2017-8-24 18:42:33

I presume reatined -> retained, yes?


leif
2017-8-24 18:51:55

Oh wait, no. the function you can’t call multiple times is the set-callback function, not the callback itself.


leif
2017-8-24 18:52:13

Which means hmmph. I’m back to not know why I’m segfaulting. Thanks anyway. :slightly_smiling_face:


lexi.lambda
2017-8-24 19:19:01

@mflatt I have a program that seems to expand differently in a sandbox vs. in a “real” top level REPL. Is this expected? Are the differences documented anywhere?


mflatt
2017-8-24 20:17:01

@lexi.lambda That shouldn’t normally happen, but it would be difficult to list all the ways that a namespace can be configured differently. Can you provide an example?


mflatt
2017-8-24 20:18:34

@leif Are you working in DrRacket or plain Racket? Going back to your earlier example, a (displayln "here") definitely wouldn’t work in atomic mode in DrRacket, and it’s not ok in general, so the crash could be something like that.


leif
2017-8-24 20:25:06

@mflatt plain cmdline racket.


leif
2017-8-24 20:25:26

I thought it was only in automic mode if you give it #:automic? #t


mflatt
2017-8-24 20:25:51

The #:async-apply callback is always in atomic mode


leif
2017-8-24 20:26:06

Ah okay.


leif
2017-8-24 20:26:33

Hmm…so I recompiled ffmpeg with pthreads explicitly disabled. And I”m still getting segfaults. So its probably something else.


leif
2017-8-24 20:28:59

@mflatt FWIW, here is the C half of the call: void (*racket_log_callback)(void*, int, const char*) = NULL; void set_racket_log_callback(void (*callback)(void*, int, const char*)) { racket_log_callback = callback; }


leif
2017-8-24 20:29:31

And then later on: void ffmpeg_log_callback(void * avcl, int level, const char * fmt, va_list vl) { int buffsize; char *buff; ... buffsize = ... buff = malloc((buffsize + 1) * sizeof(char)); vsnprintf(buff, buffsize + 1, fmt, vl); if(racket_log_callback) { racket_log_callback(avcl, level, buff); } else { free(buff); } }


lexi.lambda
2017-8-24 20:32:21

@mflatt I am having a hard time coming up with a way to reduce it to a minimal test case, but it happens with some Hackett code.


lexi.lambda
2017-8-24 20:33:14

I’m starting a REPL with racket -iI hackett and running the same code as with a sandbox created with (make-evaluator 'hackett #:require '((submod hackett configure-runtime))).


leif
2017-8-24 20:37:31

OH…interesting. If I call the callback within the function (rather than storing it for later), it works out just fine…


leif
2017-8-24 20:37:45

It seems to be the racket_log_callback = callback that is problematic.


leif
2017-8-24 20:38:24

Which is odd because the function being passed in is a module level function.


leif
2017-8-24 20:39:49

AH, okay.


leif
2017-8-24 20:40:01

@samth It looks like a module level variable WILL get GCed.


leif
2017-8-24 20:40:06

And I suspect its a phase issue.


samth
2017-8-24 20:42:56

Right, if the whole module instance itself is collected


leif
2017-8-24 20:45:34

Yup, but it seems like it happens as part of compilation.


leif
2017-8-24 20:45:43

Although that could just be something strange I’m doing with my setup.


leif
2017-8-24 20:45:47

Its hard for me to tell.


leif
2017-8-24 20:45:50

Anyway, thanks. :slightly_smiling_face:


leif
2017-8-24 20:53:47

Now if only I could attach a will to a module itself…


lexi.lambda
2017-8-24 22:37:37

@mflatt I managed to get a test case: #lang racket (require racket/sandbox syntax/location) (module forms racket (require (for-syntax racket/syntax) syntax/parse/define) (provide mac1) (define-syntax-parser mac1 [(_) #:with id (generate-temporary) #'(define id (mac2 id))]) (define-syntax-parser mac2 [(_ id:id) (local-expand #'id 'expression '()) #'(displayln "mac2" (current-error-port))])) ; works, prints "mac2" (void (make-evaluator 'racket/base #:requires (list (quote-module-path forms)) '(mac1))) ; fails (void ((make-evaluator 'racket/base #:requires (list (quote-module-path forms))) '(mac1)))


lexi.lambda
2017-8-24 22:38:21

Adjusting the expansion of mac1 to use the (define-syntaxes (id) (values)) hack makes both work. But the fact that there is a difference is mysterious!


mflatt
2017-8-24 23:44:09

@lexi.lambda I see that this is yet another case where racket7 seems to behave better, so it’s likely a bug in module->namespace handling in the current racket; I should be able to look into it more tomorrow


lexi.lambda
2017-8-24 23:49:36

@mflatt No worries, I worked around it with a define-syntaxes forward declaration (and I would like to support existing Racket versions, anyway). Cool to see that racket7 is better here, though. :)


vpm
2017-8-25 02:55:18

@vpm has joined the channel