Ejemplo n.º 1
0
/** 
 * @see free_tmpfiles
 * @see tmpfiles
 *
 */
const char *
tmpfile_name (void)
{
  /* If this is the first time that this routine is run, set up the
     list and add the destructors to the cleanup functions. */
  if (tmpfiles == NULL)
    {
      /** @note @parblock Incorperate GL_LINKED_LIST's feature to
	  make all actions on it signal safe.  This is turned on in
	  configure.ac by invoking:

	  @code
	  AC_DEFINE([SIGNAL_SAFE_LIST], [1],
	            [Define if lists must be signal-safe.])
	  @endcode

	  Thus this can be safely cleaned up while catching a fatal
	  signal.  @endparblock 
      */
      tmpfiles = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
      /* Register the free_tmpfiles cleanup function so that it is
	 called when the program exits and whenever the program
	 recieves a fatal signal. */
      atexit (free_tmpfiles);
      at_fatal_signal (free_tmpfiles);
    }

  /* Determine the name of the temporary file. */
  char *out = xstrdup ("compilerXXXXXX");
  int fd = gen_tempname (out, 0, 0, GT_FILE);
  if (fd < 0)
    error (1, errno, _("FATAL: failed to create temporary file"));
  else if (close (fd))
    error (1, errno, _("FATAL: failed to close the temporary file"));

  /* Add the entry to the list of temporary files. */
  gl_list_add_last (tmpfiles, out);

  return out;
}
/* Register a subprocess as being a slave process.  This means that the
   subprocess will be terminated when its creator receives a catchable fatal
   signal or exits normally.  Registration ends when wait_subprocess()
   notices that the subprocess has exited.  */
void
register_slave_subprocess (pid_t child)
{
  static bool cleanup_slaves_registered = false;
  if (!cleanup_slaves_registered)
    {
      atexit (cleanup_slaves);
      at_fatal_signal (cleanup_slaves);
      cleanup_slaves_registered = true;
    }

  /* Try to store the new slave in an unused entry of the slaves array.  */
  {
    slaves_entry_t *s = slaves;
    slaves_entry_t *s_end = s + slaves_count;

    for (; s < s_end; s++)
      if (!s->used)
        {
          /* The two uses of 'volatile' in the slaves_entry_t type above
             (and ISO C 99 section 5.1.2.3.(5)) ensure that we mark the
             entry as used only after the child pid has been written to the
             memory location s->child.  */
          s->child = child;
          s->used = 1;
          return;
        }
  }

  if (slaves_count == slaves_allocated)
    {
      /* Extend the slaves array.  Note that we cannot use xrealloc(),
         because then the cleanup_slaves() function could access an already
         deallocated array.  */
      slaves_entry_t *old_slaves = slaves;
      size_t new_slaves_allocated = 2 * slaves_allocated;
      slaves_entry_t *new_slaves =
        (slaves_entry_t *)
        malloc (new_slaves_allocated * sizeof (slaves_entry_t));
      if (new_slaves == NULL)
        {
          /* xalloc_die() will call exit() which will invoke cleanup_slaves().
             Additionally we need to kill child, because it's not yet among
             the slaves list.  */
          kill (child, TERMINATOR);
          xalloc_die ();
        }
      memcpy (new_slaves, old_slaves,
              slaves_allocated * sizeof (slaves_entry_t));
      slaves = new_slaves;
      slaves_allocated = new_slaves_allocated;
      /* Now we can free the old slaves array.  */
      if (old_slaves != static_slaves)
        free (old_slaves);
    }
  /* The three uses of 'volatile' in the types above (and ISO C 99 section
     5.1.2.3.(5)) ensure that we increment the slaves_count only after the
     new slave and its 'used' bit have been written to the memory locations
     that make up slaves[slaves_count].  */
  slaves[slaves_count].child = child;
  slaves[slaves_count].used = 1;
  slaves_count++;
}