Why do ncurses fail to reload a dynamic library?

I follow this blog post on Interactive Programming in C. The general ideal behind it is that it displays the implementation of Conway Game of Life in ncurses , but the game logic loads like a dynamic library. The main() loop controls .so for the game and reloads it interactively if it finds a newer version.

I tried this on LinuxMint 17, but ncurses freezes when the shared library is dynamically reloaded. I put in some fprintf debugs and kept track of the program in GDB, and the program seems to reload the library correctly and continue the main loop, as usual.

It seems that ncurses problem is here, but I don't know how to debug it. The ncurses refresh() function in game.c:draw() starts to return -1 after reloading the dynamic library. Can anyone help? The code can be found on the github repo related to the blog post.

Update

It looks like the stdscr variable in the ncurses just disappears after calling dlclose() . This does not happen on my RedHat machine at work.

+5
source share
1 answer

ncurses is a dependency of your libgame.so , not a main executable. Therefore, if you unload the dynamic library and download the modified version, you will also unload ncurses and then download it again. But you cannot reinitialize it. This is why your program crashes.

The correct solution is to call endwin() in game_unload to clear the ncurses state, and then reinitialize it in game_reload :

 static void game_reload(struct game_state *state) { initscr(); raw(); timeout(0); noecho(); curs_set(0); keypad(stdscr, TRUE); } static void game_unload(struct game_state *state) { endwin(); } 

Another solution would be to force the linker to bind ncurses to the main executable. This will prevent the dynamic linker from unloading when the game library is unloaded. This can be done by adding the -Wl,--no-as-needed flag before the $(LDLIBS) variable when compiling the main executable:

 main : main.c game.h $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -Wl,--no-as-needed $(LDLIBS) 

If you prefer this solution, also consider moving the ncurses initialization / cleanup to the main.c file. There is no technical reason for this; it is simply a matter of pure coding style.

+3
source

Source: https://habr.com/ru/post/1210814/


All Articles