Re: [AD] Patch to fix race condition

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On February 28, 2010, Peter Wang wrote:
> On 2010-02-28, Trent Gamblin <trent@xxxxxxxxxx> wrote:
> > This is a rather lazy fix for this particular problem...
> > Right now loading the system driver loads allegro5.cfg
> > which tries which tries to open the file which loads
> > the file interface which initializes pthreads which prints
> > out a string in debug mode which tries to read a value
> > from the partially loaded system configuration. The easy
> > fix is I just commented out that ALLEGRO_DEBUG call,
> > but perhaps the whole idea is flawed... anyway here's
> > a patch.
> 
> How about adding an explicit way to load configuration files without
> invoking TLS, i.e. add these
> 
>     ALLEGRO_FILE *al_fopen_stdio(const char *path, const char *mode)
>     ALLEGRO_CONFIG *al_load_config_file_stdio(const char *filename)
> 
> Also maybe
> al_set_standard_file_interface -> al_set_stdio_file_interface
> 
> The following patch is untested.
> 
> Peter
> 
> 
> diff --git a/docs/src/refman/config.txt b/docs/src/refman/config.txt
> index c81e558..e548ebf 100644
> --- a/docs/src/refman/config.txt
> +++ b/docs/src/refman/config.txt
> @@ -23,15 +23,26 @@ See also: [al_create_config], [al_load_config_file]
> 
>  ## API: al_load_config_file
> 
> -Read a configuration file from disk.
> +Read a configuration file.
>  Returns NULL on error.  The configuration structure should be destroyed
>  with [al_destroy_config].
> 
> -See also: [al_save_config_file]
> +This function calls [al_fopen] so is affected by the current file
>  interface. +
> +See also: [al_save_config_file], [al_load_config_file_stdio],
> +[al_set_new_file_interface]
> +
> +## API: al_load_config_file_stdio
> +
> +Like [al_load_config_file] but always tries to open a file on disk
>  rather than +going through the file interface.  That is, it calls
>  [al_fopen_stdio] instead +of [al_fopen].  Usually you would want to use
>  [al_load_config_file]. +
> +See also: [al_load_config_file], [al_set_new_file_interface]
> 
>  ## API: al_save_config_file
> 
> -Write out a configuration file to disk.
> +Write out a configuration file.
>  Returns true on success, false on error.
> 
>  See also: [al_load_config_file]
> diff --git a/docs/src/refman/file.txt b/docs/src/refman/file.txt
> index c2ecc31..3072b2b 100644
> --- a/docs/src/refman/file.txt
> +++ b/docs/src/refman/file.txt
> @@ -55,7 +55,7 @@ Newline translations can be useful for text files but
>  is disastrous for binary files.  To avoid this behaviour you need to
>  open file streams in binary mode by using a mode argument containing a
>  "b", e.g. "rb", "wb".
> 
> -See also: [al_set_new_file_interface].
> +See also: [al_set_new_file_interface], [al_fopen_stdio].
> 
>  ## API: al_fclose
> 
> @@ -286,6 +286,15 @@ native end-of-line sequences, e.g. CR/LF instead of
>  LF.
> 
>  ## Standard I/O specific routines
> 
> +## API: al_fopen_stdio
> +
> +Like [al_fopen] but always tries to open a file on disk rather than
>  going +through the file interface.  That is, it it unaffected by
> +[al_set_new_file_interface].
> +Usually you would want to use [al_fopen] instead.
> +
> +See also: [al_set_new_file_interface], [al_fopen]
> +
>  ### API: al_fopen_fd
> 
>  Create an [ALLEGRO_FILE] object that operates on an open file descriptor
>  using diff --git a/include/allegro5/config.h b/include/allegro5/config.h
>  index 6d39511..03a2f00 100644
> --- a/include/allegro5/config.h
> +++ b/include/allegro5/config.h
> @@ -15,6 +15,7 @@ AL_FUNC(void, al_set_config_value, (ALLEGRO_CONFIG
>  *config, const char *section, AL_FUNC(void, al_add_config_comment,
>  (ALLEGRO_CONFIG *config, const char *section, const char *comment));
>  AL_FUNC(const char*, al_get_config_value, (const ALLEGRO_CONFIG *config,
>  const char *section, const char *key)); AL_FUNC(ALLEGRO_CONFIG*,
>  al_load_config_file, (const char *filename)); +AL_FUNC(ALLEGRO_CONFIG*,
>  al_load_config_file_stdio, (const char *filename)); AL_FUNC(bool,
>  al_save_config_file, (const ALLEGRO_CONFIG *config, const char
>  *filename)); AL_FUNC(void, al_merge_config_into, (ALLEGRO_CONFIG
>  *master, const ALLEGRO_CONFIG *add)); AL_FUNC(ALLEGRO_CONFIG *,
>  al_merge_config, (const ALLEGRO_CONFIG *cfg1, const ALLEGRO_CONFIG
>  *cfg2)); diff --git a/include/allegro5/file.h b/include/allegro5/file.h
> index d80d6de..d54fe89 100644
> --- a/include/allegro5/file.h
> +++ b/include/allegro5/file.h
> @@ -76,6 +76,7 @@ AL_FUNC(ALLEGRO_USTR *, al_fget_ustr, (ALLEGRO_FILE
>  *f)); AL_FUNC(int, al_fputs, (ALLEGRO_FILE *f, const char *p));
> 
>  /* Specific to stdio backend. */
> +AL_FUNC(ALLEGRO_FILE*, al_fopen_stdio, (const char *path, const char
>  *mode)); AL_FUNC(ALLEGRO_FILE*, al_fopen_fd, (int fd, const char
>  *mode)); AL_FUNC(ALLEGRO_FILE*, al_make_temp_file, (const char *tmpl,
>        ALLEGRO_PATH **ret_path));
> diff --git a/src/config.c b/src/config.c
> index 79107f9..2b531e6 100644
> --- a/src/config.c
> +++ b/src/config.c
> @@ -329,9 +329,7 @@ static bool readline(ALLEGRO_FILE *file, ALLEGRO_USTR
>  *line) }
> 
> 
> -/* Function: al_load_config_file
> - */
> -ALLEGRO_CONFIG *al_load_config_file(const char *filename)
> +static ALLEGRO_CONFIG *load_config_file(ALLEGRO_FILE *file)
>  {
>     ALLEGRO_CONFIG *config;
>     ALLEGRO_CONFIG_SECTION *current_section = NULL;
> @@ -339,16 +337,9 @@ ALLEGRO_CONFIG *al_load_config_file(const char
>  *filename) ALLEGRO_USTR *section;
>     ALLEGRO_USTR *key;
>     ALLEGRO_USTR *value;
> -   ALLEGRO_FILE *file;
> 
> -   file = al_fopen(filename, "r");
> -   if (!file) {
> -      return NULL;
> -   }
> -
>     config = al_create_config();
>     if (!config) {
> -      al_fclose(file);
>        return NULL;
>     }
> 
> @@ -393,8 +384,42 @@ ALLEGRO_CONFIG *al_load_config_file(const char
>  *filename) al_ustr_free(key);
>     al_ustr_free(value);
> 
> +   return config;
> +}
> +
> +
> +/* Function: al_load_config_file
> + */
> +ALLEGRO_CONFIG *al_load_config_file(const char *filename)
> +{
> +   ALLEGRO_CONFIG *config;
> +   ALLEGRO_FILE *file;
> +
> +   file = al_fopen(filename, "r");
> +   if (!file) {
> +      return NULL;
> +   }
> +
> +   config = load_config_file(file);
>     al_fclose(file);
> +   return config;
> +}
> +
> +
> +/* Function: al_load_config_file_stdio
> + */
> +ALLEGRO_CONFIG *al_load_config_file_stdio(const char *filename)
> +{
> +   ALLEGRO_CONFIG *config;
> +   ALLEGRO_FILE *file;
> 
> +   file = al_fopen_stdio(filename, "r");
> +   if (!file) {
> +      return NULL;
> +   }
> +
> +   config = load_config_file(file);
> +   al_fclose(file);
>     return config;
>  }
> 
> diff --git a/src/file_stdio.c b/src/file_stdio.c
> index 2dd2435..0f727fd 100644
> --- a/src/file_stdio.c
> +++ b/src/file_stdio.c
> @@ -87,7 +87,9 @@ ALLEGRO_FILE *al_fopen_fd(int fd, const char *mode)
>  }
> 
> 
> -static ALLEGRO_FILE *file_stdio_fopen(const char *path, const char
>  *mode) +/* Function: al_fopen_stdio
> + */
> +ALLEGRO_FILE *al_fopen_stdio(const char *path, const char *mode)
>  {
>     FILE *fp;
>     ALLEGRO_FILE_STDIO *f;
> @@ -256,7 +258,7 @@ Error:
> 
>  const struct ALLEGRO_FILE_INTERFACE _al_file_interface_stdio =
>  {
> -   file_stdio_fopen,
> +   al_fopen_stdio,
>     file_stdio_fclose,
>     file_stdio_fread,
>     file_stdio_fwrite,
> diff --git a/src/system_new.c b/src/system_new.c
> index 70e961d..1880b62 100644
> --- a/src/system_new.c
> +++ b/src/system_new.c
> @@ -107,17 +107,20 @@ static void read_allegro_cfg(void)
>     /* We cannot use any logging in this function as it would cause the
>      * logging system to be initialised before all the relevant config
>  files * have been read in.
> +    *
> +    * We use al_load_config_file_stdio instad of al_load_config_file to
>  avoid +    * using any TLS while TLS might not be fully set up.
>      */
> 
>  #if defined ALLEGRO_UNIX && !defined ALLEGRO_GP2XWIZ && !defined
>  ALLEGRO_IPHONE ALLEGRO_CONFIG *temp;
>     ALLEGRO_PATH *path;
> 
> -   active_sysdrv->config = al_load_config_file("/etc/allegro5rc");
> +   active_sysdrv->config = al_load_config_file_stdio("/etc/allegro5rc");
> 
>     path = _al_unix_get_path(ALLEGRO_USER_HOME_PATH);
>     al_set_path_filename(path, "allegro5rc");
> -   temp = al_load_config_file(al_path_cstr(path, '/'));
> +   temp = al_load_config_file_stdio(al_path_cstr(path, '/'));
>     if (temp) {
>        if (active_sysdrv->config) {
>           al_merge_config_into(active_sysdrv->config, temp);
> @@ -129,7 +132,7 @@ static void read_allegro_cfg(void)
>     }
>     al_free_path(path);
> 
> -   temp = al_load_config_file("allegro5.cfg");
> +   temp = al_load_config_file_stdio("allegro5.cfg");
>     if (temp) {
>        if (active_sysdrv->config) {
>           al_merge_config_into(active_sysdrv->config, temp);
> @@ -140,7 +143,7 @@ static void read_allegro_cfg(void)
>        }
>     }
>  #else
> -   active_sysdrv->config = al_load_config_file("allegro5.cfg");
> +   active_sysdrv->config = al_load_config_file_stdio("allegro5.cfg");
>  #endif
>  }
> 
> diff --git a/src/tls.c b/src/tls.c
> index 96b3971..055ddf0 100644
> --- a/src/tls.c
> +++ b/src/tls.c
> @@ -754,21 +754,20 @@ ALLEGRO_MEMORY_BLENDER _al_get_memory_blender()
> 
> 
>  /* Function: al_get_new_file_interface
> - * FIXME: added a work-around for the situation where TLS has not yet
>  been - * initialised when this function is called. This may happen if
>  Allegro - * tries to load a configuration file before the system has
>  been - * initialised. Should probably rethink the logic here...
>   */
>  const ALLEGRO_FILE_INTERFACE *al_get_new_file_interface(void)
>  {
>     thread_local_state *tls;
> 
> -   if ((tls = tls_get()) == NULL)
> +   if ((tls = tls_get()) == NULL) {
>        return &_al_file_interface_stdio;
> +   }
> 
>     /* FIXME: this situation should never arise because tls_ has the
>  stdio * interface set as a default, but it arises on OS X if
>      * pthread_getspecific() is called before pthreads_thread_init()...
> +    *
> +    * Does this still happen? --pw
>      */
>     if (tls->new_file_interface)
>        return tls->new_file_interface;

I must have missed it, but what exactly is the reason tls can't be setup 
before ANYTHING else is done in al_init?

-- 
Thomas Fjellstrom
tfjellstrom@xxxxxxxxxx




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/