Having Trouble with exit(1) - Stalling Program
AceBlkwell

I am still working on the Vivace tutorial. I'm working with sound now. Due to an oversight on my part I didn't catch the file downloaded didn't have the same name as the code. The program would drop into a "must_init" function design to cut down on repetitive coding. The program wouldn't print via the printf command so I didn't realize the program was crashing within this function. The Include section included stdio.h but I also included cstdio. It solved the print problem but not the crash/hang.
It appears the exit(1) command is where the program is stalling. I have to close the program within the IDE to get it to clear out. There is no window or console that pops up. This also made it a pain to run down.

Having said all of that, my question is, why would exit(1) stall? Is there a better command? I'm compiling with g++.

Reading over the code, could the problem with the function being void, yet exit appears to be trying to return something?

If you are interested here are the snippets of code involved

#SelectExpand
1 2ALLEGRO_SAMPLE* elephant = al_load_sample("elephant.wav");// file was actually audio_elephant.wav 3must_init(elephant, "elephant"); 4 5void must_init(bool test, const char *description) 6{ 7 if(test) return; 8 printf("couldn't initialize %s\n", description); 9 exit(1); // after including cstdio this is where it's stalling. It's not making it out of the function. 10}

Thanks

DanielH

If not too big, post the entire file. Got to be something else. Nothing looks wrong with function. Except, I'd make it cleaner.

void must_init(bool test, const char *description)
{
  //if(test) return;
  if (!test)
  {
    printf("couldn't initialize %s\n", description);
    exit(1); // after including cstdio this is where it's stalling. It's not making it out of the function. 
  }
}

AceBlkwell

Here is the code. Keep in mind
1- The name of the sound file is still wrong, for the sake of the failure
2- It's a little patch work because we started with a working program then was asked to replace sections as the lessons progressed.
3- I added iostream so I could use std::cout. I haven't found a good "step" IDE since MSQuick C. So I use std::cout to see if a program is making it to a given point or what variable values are at that point.
4- allcolor_A5.h is my own file for colors obliviously. This way I don't' have to al_map_rgb(0,255,0), I can just use BR_GREEN.

#SelectExpand
1 2#include <stdio.h> 3#include <stdlib.h> 4#include <allegro5/allegro5.h> 5#include <allegro5/allegro_font.h> 6#include <allegro5/allegro_primitives.h> 7#include <allegro5/allegro_audio.h> 8#include <allegro5/allegro_acodec.h> 9#include <allcolor_A5.h> 10#include <iostream> 11#include <cstdio> 12 13#define KEY_SEEN 1 14#define KEY_RELEASED 2 15 16void must_init(bool test, const char *description) 17{ 18 if(test) return; 19 printf("couldn't initialize %s\n", description); 20 exit(1); 21} 22 23int main() 24{ 25 must_init(al_init(), "allegro"); 26 must_init(al_install_keyboard(), "keyboard"); 27 must_init(al_install_mouse(), "mouse"); 28 must_init(al_install_audio(), "audio"); 29 must_init(al_init_acodec_addon(), "audio codecs"); 30 must_init(al_reserve_samples(16), "reserve samples"); 31 32 ALLEGRO_SAMPLE* elephant = al_load_sample("elephant.wav"); 33 must_init(elephant, "elephant"); 34 35 ALLEGRO_TIMER* timer = al_create_timer(1.0 / 30.0); 36 must_init(timer, "timer"); 37 38 ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue(); 39 must_init(queue, "queue"); 40 41 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); 42 al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST); 43 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); 44 45 ALLEGRO_DISPLAY* disp = al_create_display(640, 480); 46 must_init(disp, "display"); 47 48 ALLEGRO_FONT* font = al_create_builtin_font(); 49 must_init(font, "font"); 50 51 must_init(al_init_primitives_addon(), "primitives"); 52 al_register_event_source(queue, al_get_keyboard_event_source()); 53 al_register_event_source(queue, al_get_display_event_source(disp)); 54 al_register_event_source(queue, al_get_timer_event_source(timer)); 55 al_register_event_source(queue, al_get_mouse_event_source()); 56 57 bool done = false; 58 bool redraw = true; 59 ALLEGRO_EVENT event; 60 61 float x, y; 62 x = 100; 63 y = 100; 64 float dx, dy; 65 dx = 0; 66 dy = 0; 67 unsigned char key[ALLEGRO_KEY_MAX]; 68 memset(key, 0, sizeof(key)); 69 70 al_grab_mouse(disp); 71 al_hide_mouse_cursor(disp); 72 al_start_timer(timer); 73 74 75 // ALLEGRO_KEYBOARD_STATE ks; 76 while(1) 77 { 78 al_wait_for_event(queue, &event); 79 80 /* switch(event.type) 81 { 82 case ALLEGRO_EVENT_TIMER: 83 if(key[ALLEGRO_KEY_UP]) 84 y-=2; 85 if(key[ALLEGRO_KEY_DOWN]) 86 y+=2; 87 if(key[ALLEGRO_KEY_LEFT]) 88 x-=2; 89 if(key[ALLEGRO_KEY_RIGHT]) 90 x+=2; 91 92 if(key[ALLEGRO_KEY_ESCAPE]) 93 done = true; 94 95 96 for(int i = 0; i < ALLEGRO_KEY_MAX; i++) 97 key[i] &= KEY_SEEN; 98 99 redraw = true; 100 break; 101 102 case ALLEGRO_EVENT_KEY_DOWN: 103 key[event.keyboard.keycode] = KEY_SEEN | KEY_RELEASED; 104 break; 105 case ALLEGRO_EVENT_KEY_UP: 106 key[event.keyboard.keycode] &= KEY_RELEASED; 107 break; 108 109 case ALLEGRO_EVENT_DISPLAY_CLOSE: 110 done = true; 111 break; 112 }*/ 113 switch(event.type) 114 { 115 case ALLEGRO_EVENT_TIMER: 116 if(key[ALLEGRO_KEY_ESCAPE]) 117 done = true; 118 119 x += dx; 120 y += dy; 121 122 if(x < 0) 123 { 124 x *= -1; 125 dx *= -1; 126 } 127 if(x > 640) 128 { 129 x -= (x - 640) * 2; 130 dx *= -1; 131 } 132 if(y < 0) 133 { 134 y *= -1; 135 dy *= -1; 136 } 137 if(y > 480) 138 { 139 y -= (y - 480) * 2; 140 dy *= -1; 141 } 142 143 dx *= 0.9; 144 dy *= 0.9; 145 146 for(int i = 0; i < ALLEGRO_KEY_MAX; i++) 147 key[i] &= KEY_SEEN; 148 149 redraw = true; 150 break; 151 152 case ALLEGRO_EVENT_MOUSE_AXES: 153 dx += event.mouse.dx * 0.1; 154 dy += event.mouse.dy * 0.1; 155 al_set_mouse_xy(disp, 320, 240); 156 break; 157 158 case ALLEGRO_EVENT_KEY_DOWN: 159 if(event.keyboard.keycode == ALLEGRO_KEY_E) 160 al_play_sample(elephant, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); 161 if(event.keyboard.keycode != ALLEGRO_KEY_ESCAPE) 162 break; 163 case ALLEGRO_EVENT_KEY_UP: 164 key[event.keyboard.keycode] &= KEY_RELEASED; 165 break; 166 167 case ALLEGRO_EVENT_DISPLAY_CLOSE: 168 done = true; 169 break; 170 } 171 if(done) 172 break; 173 174 if(redraw && al_is_event_queue_empty(queue)) 175 { 176 177 al_clear_to_color(al_map_rgb(0, 0, 0)); 178 al_draw_text(font, al_map_rgb(255, 255, 255), 640/2, 480/2, ALLEGRO_ALIGN_CENTER, "Knock knock, it's Nelly"); 179 al_draw_filled_rectangle(x, y, x + 10, y + 10, al_map_rgb(255, 0, 0)); 180 181 al_flip_display(); 182 183 redraw = false; 184 } 185 } 186 187 al_destroy_sample(elephant); 188 al_destroy_font(font); 189 al_destroy_display(disp); 190 al_destroy_timer(timer); 191 al_destroy_event_queue(queue); 192 193 return 0; 194}

DanielH

At which step is it freezing? When it is loading the file?

I'm staring at it and don't see anything. I can test it later tonight when I'm home. I don't normally use exit.

cstdio over stdio.h if you are using C++.

Quote:

The difference (which is neither minor nor a matter of style) is that stdio. h and other C-like libraries when imported in a C++ file may pollute the global namespace, while the corresponding C++ headers (cstdio, cstdlib, cassert) place the corresponding functions, variables, etc., in the std namespace.

AceBlkwell

The program gets down to

ALLEGRO_SAMPLE* elephant = al_load_sample("elephant.wav");
must_init(elephant, "elephant");

It attempts to load the sound file. Then enters must_init. While in must_init, it gets down past printf but doesn't come back out of the function. There is only one command after printf, exit(1) so I assume that's where it's stalling.

void must_init(bool test, const char *description)
{
if(test) return;
printf("couldn't initialize %s\n", description);
exit(1);
}

All the other inits are successful so it never gets to exit(1).

DanielH

I don't think it's the exit, but for testing purposes. Add another printf test string after the exit before the function ends.

AceBlkwell

Daniel, don't waste a lot of time on it. I was just curious if there was an alternative to exit(1) or if it was problematic with C++.

To your suggestion, here are my results.

Before File load
Before must_init in main
After If return in must_init
couldn't initialize elephant
After printf in must_init

If didn't make it after exit(1)

#SelectExpand
1 2void must_init(bool test, const char *description) 3{ 4 if(test) return; 5 std::cout<<"After If return in must_init"<<std::endl; // 6 printf("couldn't initialize %s\n", description); 7 std::cout<<"After printf in must_init"<<std::endl; // 8 exit(1); 9 std::cout<<"After exit(1) in must_init"<<std::endl; // 10} 11 12 13int main() 14{ 15 must_init(al_init(), "allegro"); 16 must_init(al_install_keyboard(), "keyboard"); 17 must_init(al_install_mouse(), "mouse"); 18 must_init(al_install_audio(), "audio"); 19 must_init(al_init_acodec_addon(), "audio codecs"); 20 must_init(al_reserve_samples(16), "reserve samples"); 21 22 std::cout<<"Before File load"<<std::endl; // 23 ALLEGRO_SAMPLE* elephant = al_load_sample("elephant.wav"); 24 std::cout<<"Before must_init in main"<<std::endl; // 25 must_init(elephant, "elephant"); 26 std::cout<<"After must_init in main"<<std::endl; //

DanielH
#SelectExpand
1// remove exit 2bool must_init(bool test, const char *description) 3{ 4 if (!test) 5 { 6 std::cout << "couldn't initialize" << description < <std::endl; 7 } 8 9 return test; 10} 11 12int main() 13{ 14 if (!(must_init(al_init(), "allegro")) return -1; 15 16}

This is mine

    // what are we attempting
    std::cout << "Initializing Allegro Library: ";
    if (!al_init())
    {
        std::cout << "failed" << std::endl;
        return -1;
    }
    std::cout << "pass" << std::endl;

it does get messy

#SelectExpand
1int32_t init() 2{ 3 std::cout << "Initialization Begin" << std::endl; 4 5 std::cout << "Initializing Allegro Library: "; 6 if (!al_init()) 7 { 8 std::cout << "failed" << std::endl; 9 return -1; 10 } 11 std::cout << "pass" << std::endl; 12 13 std::cout << "Initializing Mouse: "; 14 if (!al_install_mouse()) 15 { 16 std::cout << "failed" << std::endl; 17 return -1; 18 } 19 std::cout << "pass" << std::endl; 20 21 std::cout << "Initializing Keyboard: "; 22 if (!al_install_keyboard()) 23 { 24 std::cout << "failed" << std::endl; 25 return -1; 26 } 27 std::cout << "pass" << std::endl; 28 29 std::cout << "Initializing Image Addon: "; 30 if (!al_init_image_addon()) 31 { 32 std::cout << "failed" << std::endl; 33 return -1; 34 } 35 std::cout << "pass" << std::endl; 36 37 std::cout << "Creating Display: "; 38 al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE); 39 if (!(this->m_display = al_create_display(App::SCREEN_W, App::SCREEN_H))) 40 { 41 std::cout << "failed" << std::endl; 42 return -1; 43 } 44 std::cout << "pass" << std::endl; 45 46 ALLEGRO_BITMAP* icon = al_load_bitmap("data\\images\\icon.png"); 47 if (icon) 48 { 49 al_set_display_icon(this->m_display, icon); 50 al_destroy_bitmap(icon); 51 } 52 al_set_window_title(this->m_display, App::APPNAME); 53 54 std::cout << "Creating Event Queue: "; 55 if (!(this->m_queue = al_create_event_queue())) 56 { 57 std::cout << "failed" << std::endl; 58 return -1; 59 } 60 std::cout << "pass" << std::endl; 61 62 std::cout << "Creating Logic Timer: "; 63 if (!(this->m_timer = al_create_timer(1.0/App::TIMING))) 64 { 65 std::cout << "failed" << std::endl; 66 return -1; 67 } 68 std::cout << "pass" << std::endl; 69 70 al_register_event_source(this->m_queue, al_get_display_event_source(this->m_display)); 71 al_register_event_source(this->m_queue, al_get_timer_event_source(this->m_timer)); 72 al_register_event_source(this->m_queue, al_get_keyboard_event_source()); 73 al_register_event_source(this->m_queue, al_get_mouse_event_source()); 74 75 al_start_timer(this->m_timer); 76 77 std::cout << "Initialization Complete" << std::endl << std::endl; 78 79 return 0; 80}

Personally, I don't like leaving things hanging. My shutdown function always gets called even if there is an error in init. In it, every object I allocated is checked and unallocated.

int main()
{
    if (init() ==0)
    {
        // proceed
        loop();
    }
    shutdown():
}

AceBlkwell

Thanks for the insight Daniel. I appreciate the time.

Edgar Reynaldo

NVM

That said, avoid nasty things like exit and abort. It's easy enough to return non-zero in main.

Also, must init should also report success, not just failure.

DanielH

I'm home and tested your code. It does just as expected. runs and exits after failing to load elephant.

output: "couldn't initialize elephant"

I put a wav file of my own and the program plays it when I press E. Some issues, how to exit program? You turned off the mouse cursor so I could not press the close button. You don't have any key presses that close the program either. I was able to close it pressing Alt+f4.

{"name":"613302","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/b\/cbe4db979eece65810032c1c2bb1fb22.png","w":789,"h":590,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/b\/cbe4db979eece65810032c1c2bb1fb22"}613302

AceBlkwell

Could be my computer at work. I ran it from home. Still Eclipse IDE but on Linux. It worked just like you said. Must have just been the computer at work. Doesn't make sense.
The lesson before was for the mouse. It was showing how to capture it in the window. On my work (Windows 10) I can Alt Tab to another window and the mouse will go with me. On Linux I almost had to reboot the computer. No matter which program I tabbed to, the mouse stayed with the elephant program.
As for the Esc key, the code has been so jumbled up, I'm not sure why it doesn't work but it didn't.
In any case there doesn't seem to be anything wrong with exit(1) which was my first question. Sorry if I wasted your time. Thanks again for the help.

Edgar Reynaldo

If your program was hanging, it was probably because of a loose thread that was still running. Probably allegro's audio or window thread.

AceBlkwell

Could be Edgar.

I still think it's something to do with Windows /Eclipse IDE / Mingw32. Or a combo there of. Here is why I say that
- I can run the program from outside of the IDE and it will print the "could not init XXXX" line and quit.
- Moving too quick, I duplicated my mistake with the Gameplay code, as the audio files all started with audio_XXXXXX. It was a new program and it did the same thing. No printing and it would just hang. I've have to check a box in Eclipse to get it to stop. Fortunately this time I only made the mistake once ;D.

Thanks for the follow up.

Edgar Reynaldo

If you're using the same code as before, you haven't shutdown audio or allegro itself.

Dizzy Egg

This code is horrible to me; why call every library initialisation method and then pass an optional null into a void method with a null as bool? Why not just have a setup function that returns a bool result and determine whether or not to continue or not based on setup success?

AceBlkwell

Yeah, I didn't create the code so I can't say why they did what they did. I figured the programmer knew more about it than I did. It seems to work well enough if the ducks are in a row.

Thread #618781. Printed from Allegro.cc