From 9a2f4e10e71aa1c0c2970f807fe14000861b602b Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 4 Aug 2012 03:46:11 +0200 Subject: [PATCH] mplayer: never exit mplayer from within the play loop The only place exit_player() should be called is the main() function. exit_player() should be the only function allowed to call exit(). This makes it easier to guarantee proper deinitialization, and allows using the --leak-report flag without showing false positives. The quit slave command now sets a flag only. It uses the same mechanism that's normally used to advance to the next file on the playlist, so the rest of the playback path should be able to react to the quit command quickly enough. That is, the player should react just as fast to quit requests in practice as before this commit. In reinit_audio_chain(), the player was actually exited if init_audio_filters() failed. Reuse the normal error handling path to handle this condition. --- command.c | 5 +++-- libvo/x11_common.c | 1 - mp_core.h | 5 ++++- mplayer.c | 46 ++++++++++++++++++++++++++-------------------- parser-cfg.c | 2 +- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/command.c b/command.c index 6ec37d4f26..83a0ca8755 100644 --- a/command.c +++ b/command.c @@ -2872,8 +2872,9 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) break; case MP_CMD_QUIT: - exit_player_with_rc(mpctx, EXIT_QUIT, - (cmd->nargs > 0) ? cmd->args[0].v.i : 0); + mpctx->stop_play = PT_QUIT; + mpctx->quit_player_rc = (cmd->nargs > 0) ? cmd->args[0].v.i : 0; + break; case MP_CMD_PLAYLIST_NEXT: case MP_CMD_PLAYLIST_PREV: diff --git a/libvo/x11_common.c b/libvo/x11_common.c index 210f618533..fc6875b7d5 100644 --- a/libvo/x11_common.c +++ b/libvo/x11_common.c @@ -193,7 +193,6 @@ static int x11_errorhandler(Display * display, XErrorEvent * event) event->error_code, event->request_code, event->minor_code); // abort(); - //exit_player("X11 error"); return 0; #undef MSGLEN } diff --git a/mp_core.h b/mp_core.h index 153869d620..31834d61e9 100644 --- a/mp_core.h +++ b/mp_core.h @@ -54,6 +54,7 @@ enum stop_play_reason { PT_NEXT_ENTRY, // prepare to play next entry in playlist PT_CURRENT_ENTRY, // prepare to play mpctx->playlist->current PT_STOP, // stop playback, clear playlist + PT_QUIT, // stop playback, quit player }; enum exit_reason { @@ -99,6 +100,9 @@ typedef struct MPContext { enum stop_play_reason stop_play; unsigned int initialized_flags; // which subsystems have been initialized + // Return code to use with PT_QUIT + int quit_player_rc; + struct content_source *sources; int num_sources; struct timeline_part *timeline; @@ -227,7 +231,6 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask); void reinit_audio_chain(struct MPContext *mpctx); void init_vo_spudec(struct MPContext *mpctx); double playing_audio_pts(struct MPContext *mpctx); -void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc); void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr); int reinit_video_chain(struct MPContext *mpctx); void pause_player(struct MPContext *mpctx); diff --git a/mplayer.c b/mplayer.c index 45b04a58cc..b25a18a460 100644 --- a/mplayer.c +++ b/mplayer.c @@ -652,7 +652,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) } } -void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc) +static void exit_player(struct MPContext *mpctx, enum exit_reason how, int rc) { uninit_player(mpctx, INITIALIZED_ALL); #if defined(__MINGW32__) || defined(__CYGWIN__) @@ -700,11 +700,6 @@ void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc) exit(rc); } -static void exit_player(struct MPContext *mpctx, enum exit_reason how) -{ - exit_player_with_rc(mpctx, how, 1); -} - #include "cfg-mplayer.h" static int cfg_include(struct m_config *conf, char *filename) @@ -714,14 +709,14 @@ static int cfg_include(struct m_config *conf, char *filename) #define DEF_CONFIG "# Write your default config options here!\n\n\n" -static void parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf) +static bool parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf) { struct MPOpts *opts = &mpctx->opts; char *conffile; int conffile_fd; if (!(opts->noconfig & 2) && m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0) - exit_player(mpctx, EXIT_NONE); + return false; if ((conffile = get_path("")) == NULL) mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "Cannot find HOME directory.\n"); else { @@ -739,10 +734,11 @@ static void parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf) } if (!(opts->noconfig & 1) && m_config_parse_config_file(conf, conffile) < 0) - exit_player(mpctx, EXIT_NONE); + return false; free(conffile); } } + return true; } #define PROFILE_CFG_PROTOCOL "protocol." @@ -1509,7 +1505,7 @@ void reinit_audio_chain(struct MPContext *mpctx) &ao->samplerate, &ao->channels, &ao->format)) { mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Error at audio filter chain " "pre-init!\n"); - exit_player(mpctx, EXIT_ERROR); + goto init_error; } if (!ao->initialized) { ao->buffersize = opts->ao_buffersize; @@ -3564,7 +3560,9 @@ static bool process_playlist_demuxer(struct MPContext *mpctx) static void idle_loop(struct MPContext *mpctx) { // ================= idle loop (STOP state) ========================= - while (mpctx->opts.player_idle_mode && !mpctx->playlist->current) { + while (mpctx->opts.player_idle_mode && !mpctx->playlist->current + && mpctx->stop_play != PT_QUIT) + { uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_VO); mp_cmd_t *cmd; while (!(cmd = mp_input_get_cmd(mpctx->input, WAKEUP_PERIOD * 1000, @@ -3818,7 +3816,7 @@ goto_enable_cache: } } #endif - goto terminate_playback; // exit_player(_("Fatal error")); + goto terminate_playback; } /* display clip info */ @@ -4033,7 +4031,12 @@ static void play_files(struct MPContext *mpctx) { for (;;) { idle_loop(mpctx); + if (mpctx->stop_play == PT_QUIT) + break; + play_current_file(mpctx); + if (mpctx->stop_play == PT_QUIT) + break; if (!mpctx->stop_play || mpctx->stop_play == AT_END_OF_FILE) mpctx->stop_play = PT_NEXT_ENTRY; @@ -4127,7 +4130,7 @@ static bool handle_help_options(struct MPContext *mpctx) return opt_exit; } -static void load_codecs_conf(struct MPContext *mpctx) +static bool load_codecs_conf(struct MPContext *mpctx) { /* Check codecs.conf. */ if (!codecs_file || !parse_codec_cfg(codecs_file)) { @@ -4135,13 +4138,14 @@ static void load_codecs_conf(struct MPContext *mpctx) if (!parse_codec_cfg(mem_ptr = get_path("codecs.conf"))) { if (!parse_codec_cfg(MPLAYER_CONFDIR "/codecs.conf")) { if (!parse_codec_cfg(NULL)) - exit_player_with_rc(mpctx, EXIT_NONE, 0); + return false; mp_tmsg(MSGT_CPLAYER, MSGL_V, "Using built-in default codecs.conf.\n"); } } free(mem_ptr); // release the buffer created by get_path() } + return true; } #ifdef PTW32_STATIC_LIB @@ -4238,7 +4242,8 @@ int main(int argc, char *argv[]) print_version(false); print_libav_versions(); - parse_cfgfiles(mpctx, mpctx->mconfig); + if (!parse_cfgfiles(mpctx, mpctx->mconfig)) + exit_player(mpctx, EXIT_NONE, 1); mpctx->playlist = talloc_struct(mpctx, struct playlist, {0}); if (m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist, @@ -4246,13 +4251,14 @@ int main(int argc, char *argv[]) { mpctx->playlist->current = mpctx->playlist->first; } else { - exit_player(mpctx, EXIT_ERROR); + exit_player(mpctx, EXIT_ERROR, 1); } - load_codecs_conf(mpctx); + if (!load_codecs_conf(mpctx)) + exit_player(mpctx, EXIT_ERROR, 1); if (handle_help_options(mpctx)) - exit_player(mpctx, EXIT_NONE); + exit_player(mpctx, EXIT_NONE, 1); mp_msg(MSGT_CPLAYER, MSGL_V, "Configuration: " CONFIGURATION "\n"); mp_tmsg(MSGT_CPLAYER, MSGL_V, "Command line:"); @@ -4264,7 +4270,7 @@ int main(int argc, char *argv[]) // no file/vcd/dvd -> show HELP: print_version(true); mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", mp_gtext(help_text)); - exit_player_with_rc(mpctx, EXIT_NONE, 0); + exit_player(mpctx, EXIT_NONE, 0); } #ifdef CONFIG_PRIORITY @@ -4281,7 +4287,7 @@ int main(int argc, char *argv[]) play_files(mpctx); - exit_player_with_rc(mpctx, EXIT_EOF, 0); + exit_player(mpctx, EXIT_EOF, mpctx->quit_player_rc); return 1; } diff --git a/parser-cfg.c b/parser-cfg.c index f6a4c67d3a..91ef37be53 100644 --- a/parser-cfg.c +++ b/parser-cfg.c @@ -41,7 +41,7 @@ static int recursion_depth = 0; /// Setup the \ref Config from a config file. /** \param config The config object. * \param conffile Path to the config file. - * \return 1 on sucess, -1 on error. + * \return 1 on sucess, -1 on error, 0 if file not accessible. */ int m_config_parse_config_file(m_config_t *config, const char *conffile) {