greg
2017-5-5 14:21:04

Oh my http package supports back to Racket 5.3.5, so I probably can’t use your retry pkg directly. :disappointed:


leif
2017-5-5 18:01:21

Does anyone know if its possible to add a callback for the Racket VM to call before the OS level process exits?


leif
2017-5-5 18:02:11

Plumbers seem to get called at a programs end, which is not necessarily the process’s end.


leif
2017-5-5 18:02:25

exit handlers seem to have the same problem.


leif
2017-5-5 18:02:48

And custodians seem to be just for freeing up memory.


thinkmoore
2017-5-5 18:08:37

you can use the FFI to add an exit handler using atexit https://linux.die.net/man/3/atexit


thinkmoore
2017-5-5 18:08:41

(for normal termination)


thinkmoore
2017-5-5 18:08:53

and signal handlers for catching (nice) kills


thinkmoore
2017-5-5 18:09:17

depending on what you want to do that could have icky concurrency interactions with the VM


thinkmoore
2017-5-5 18:09:33

(particularly signal handlers, since I think the VM might install some of its own?)


thinkmoore
2017-5-5 18:09:37

what are you trying to do


leif
2017-5-5 18:10:10

@thinkmoore True, and I will if I need to.


leif
2017-5-5 18:10:22

But I would ideally like to find a racket solution.


thinkmoore
2017-5-5 18:10:39

I don’t think there is a racket notion of anything that happens “after the program’s end”


leif
2017-5-5 18:10:40

I suppose I could use scheme_add_managed_close_on_exit


leif
2017-5-5 18:11:06

Oh sure there are, just not at the ‘process’s’ end, if that makes sense.


leif
2017-5-5 18:11:33

But ya, in principle, exit-handler runs at the end of a program.


leif
2017-5-5 18:11:42

Same with some plumbers.


thinkmoore
2017-5-5 18:13:34

doesn’t schme_add_managed_close_on_exit just add something to a custodian? which is still “end of program” (or “on custodian shutdown”)?


leif
2017-5-5 18:13:47

But I guess the problem with scheme_add_managed_close_on_exit is that I would have to make sure the current-custodian is the one associated with the process, and not just a thread.


leif
2017-5-5 18:13:59

@thinkmoore yup


leif
2017-5-5 18:14:14

There is scheme_atexit_closer


leif
2017-5-5 18:14:31

Which looks like its called on exit, but also on custodian closing.


leif
2017-5-5 18:14:42

So I would just need to find a way to ensure that its the former case.


leif
2017-5-5 18:17:10

@mflatt Do you have any thoughts.


mflatt
2017-5-5 18:21:22

@leif Registering with the custodian or plumber is likely to be right For context, what is it that you want to do on exit?


leif
2017-5-5 18:22:10

I have an ffi library that has an init() and close() funciton


leif
2017-5-5 18:22:24

They init() function can only be called once.


leif
2017-5-5 18:22:34

And once called, close() must eventually be called.


leif
2017-5-5 18:22:45

But once close() is called, I can no longer use the FFI


mflatt
2017-5-5 18:22:59

What happens if you don’t call close (e.g., the process is terminated with SIGKILL)?


leif
2017-5-5 18:23:17

Frequently the library will segfault.


leif
2017-5-5 18:23:34

Which, IMO, is a terrible design, but that’s the case.


mflatt
2017-5-5 18:23:43

It will segfault when you use it from a different process?


leif
2017-5-5 18:24:21

Ah..woops, ya, I was thinking of SIGTRM


leif
2017-5-5 18:24:27

yes, if you SIGKILL then it will just die.


leif
2017-5-5 18:24:44

Leaving whatever it was doing in some undefined state.


leif
2017-5-5 18:24:51

But that’s unavoidable.


leif
2017-5-5 18:25:07

But if you send a SIGTRM without calling close() it will segfault.


leif
2017-5-5 18:26:26

The problem with using a plumber is that I can only get the plumber for my current program, as such, if I’m running the program multiple times in one process (like say doing a raco setup), then the second time I’ve already close()ed the library.


leif
2017-5-5 18:26:52

(i’m using scheme_register_process_global to ensure that I only call init() once.


thinkmoore
2017-5-5 18:27:15

can you have that register with the current plumber?


thinkmoore
2017-5-5 18:27:21

/custodian


mflatt
2017-5-5 18:28:30

If you’re doing something that spans places, then I recommend atexit() instead of a custodian after all


leif
2017-5-5 18:29:27

@mflatt Okay, thanks.


leif
2017-5-5 18:30:08

@thinkmoore Sadly nope, because the current plumber may not be the global plumber for the process.


leif
2017-5-5 18:30:17

And in, say, the case of raco setup, it won’t be.


leif
2017-5-5 18:30:40

@mflatt Do places run in the same process? I thought they were a slightly glorified fork()


mflatt
2017-5-5 18:30:52

Same OS process


leif
2017-5-5 18:31:11

Ah, alright then.


leif
2017-5-5 18:31:48

I guess the only thing I’m worried about now is that atexit is OS-dependent, but I suspect there is an equivalent function for windows.


leif
2017-5-5 18:54:37

@thinkmoore Hmmph: couldn't get "atexit" from #f (/home/travis/racket/bin/racket: undefined symbol: atexit)


leif
2017-5-5 18:54:51

I also tried the library libc, but then I get a can’t find the library libc


leif
2017-5-5 18:55:28

Maybe I have to special case this to be libc on os x and glibc on linux.


leif
2017-5-5 18:58:57

or rather, I get: ffi-lib: couldn't open "libc.so" (/usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header)


notjack
2017-5-5 20:38:28

I could probably make adjustments to support that, could you open an issue?


leif
2017-5-5 20:45:54

@mflatt or @thinkmoore Ya, I can’t get atexit from libc. The error I get is: ffi-obj: couldn't get "atexit" from "libc.so.6" (/lib/x86_64-linux-gnu/libc.so.6: undefined symbol: atexit)


leif
2017-5-5 20:46:14

However, when I wrote a small C program to test it out: #include <stdlib.h> void bob(void) { return; } int main() { atexit(bob); return 0; }


leif
2017-5-5 20:46:19

And ran ld a.out, I got:


leif
2017-5-5 20:46:25

ldd*


leif
2017-5-5 20:46:37
        linux-vdso.so.1 (0x00007ffd2bb36000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe087a76000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe087e21000)

leif
2017-5-5 20:46:39

Thoughts?


leif
2017-5-5 20:48:03

FWIW, on osx I seem to be able to find the atexit symbol just fine.


leif
2017-5-5 20:58:53

Hmm…it looks like libc doesn’t actually have an atexit symbol (as determined by nm --dynamic), but that makes me still wonder how C linked to it.


leif
2017-5-5 21:10:02

Okay, time for another approach. @mflatt Do you have to call a close() type of function on the GUI?


leif
2017-5-5 21:10:11

(That is a process level close())


mflatt
2017-5-5 21:16:37

It does seem like the linker on Linux does something special with atexit… oh, well


mflatt
2017-5-5 21:16:44

No, the GUI doesn’t need a close()


mflatt
2017-5-5 21:20:09

I guess you could use scheme_add_managed_close_on_exit() but keep a reference count: +1 when you would have called init() in a new place, -1 on exit from a place


mflatt
2017-5-5 21:20:33

Use scheme_make_custodian(NULL) to get a custodian that acts like the root one


mflatt
2017-5-5 21:21:53

… but I’m not sure that when the main place exits, then it will explicitly shut down other places


mflatt
2017-5-5 21:23:55

You might be able to use (_fun #:in-original-place? #t ...) to register something in the main place


mflatt
2017-5-5 21:27:14

As I try to think of other strategies, part of the problem is that you can’t (I think) write a Racket callback in a non-main place that will work if that place goes away before the main place


leif
2017-5-5 21:34:12

@mflatt Ah, so like, whenever init would have been called, that’s whena new on_exit would have happeend?


leif
2017-5-5 21:34:14

happened*


mflatt
2017-5-5 21:45:55

I haven’t figured out anything that can work if the main place exits while some other place is still running. Even if you could reach atexit, that wouldn’t work if some other place is still using the library while the main place is busy running atexit callbacks.


mflatt
2017-5-5 21:51:04

Can you assume that places are never forcibly terminated (including by a main-place exit)? In that case, reference counting should work.


greg
2017-5-5 22:04:28

I just made an experimental PR on compose-app (on which retry depends).



greg
2017-5-5 22:07:22

Probably I should just write my own exp backoff retry in the tests for http.


greg
2017-5-5 22:08:01

And, I could update the docs for http to suggest, “hey if you’re using a newer Racket, retry might be a great way to use http” or something to that effect


leif
2017-5-5 22:27:55

Lets say for right now sure.


leif
2017-5-5 22:28:11

(Does raco setup use places?)


leif
2017-5-5 22:28:21

Basically that’s what’s messing things up right now.


leif
2017-5-5 22:28:38

Anyway, I’m trying reference counting.


leif
2017-5-5 22:28:46

I’ll let you know how it turns out.


leif
2017-5-5 23:13:52

@mflatt Ha, it seems to work on my machines, but on travis CI I’m getting a #<bad-value>


notjack
2017-5-5 23:26:23

Alternatively you could use Docker to run the test against a real server locally on Travis and not run that test normally


notjack
2017-5-5 23:27:01

somewhere around 6.3 / 6.4 tends to be the oldest my stuff supports because that’s when the new scribble/example lib was added


leif
2017-5-5 23:46:25

@mflatt Do you see anything immediately wrong with this: https://github.com/LeifAndersen/racket-video/blob/master/video/private/init-mlt.rkt


leif
2017-5-5 23:46:29

Its how I’m doing the counter.


leif
2017-5-5 23:46:46

But it still breaks travis, so I’m clearly doing something wrong here.


mflatt
2017-5-6 00:03:26

The first thing I see is (scheme_register_process_global counter-key (cast (box 0) _racket _pointer) That’s no good, since (box 0) is a GCable value. Use (malloc 'raw ...).


leif
2017-5-6 02:31:30

@mflatt Oh good point, thanks.


leif
2017-5-6 02:31:39

That would explain why I was getting the bad value


leif
2017-5-6 02:37:18

Btw, I think the docs for malloc are wrong, because the parameter order it gives seems to be different from the one used.


leif
2017-5-6 02:37:47

Oh wait, nvm. I just missed the line in the pros.


leif
2017-5-6 02:37:51

prose*