From: rbr4@uhura.cc.rochester.edu (Roland Roberts)
Newsgroups: comp.os.vms
Subject: VAXC stroul bug (maybe)
Summary: Sometimes drops leading two digits of hex string
Date: 15 Apr 92 18:25:24 GMT
Organization: University of Rochester (Rochester, NY)

I've recently been bitten by what seems to be a bug in the C function
stroul.  I modified GNU Emacs to allow me to attach to a process other
than the one that spawned the Emacs subprocess by translating the
logical EMACS_PARENT_PID, which I define in the JOB table.

I found that sometimes, Emacs wouldn't suspend itself and attach to
this process.  So I added a few lines to write into a file to tell me
what was going on.  I found that the logical was being translated just
fine, but that stroul sometimes ignored the the first two digits in
the PID string, resulting in a bad pid.  The format of the call is
`pid = stroul (string, NULL, 16)' where `string' is the pointer
returned by `getenv' and `pid' is declared as unsigned long.

However, I can't get the same sort of behavior in a test program.  I
have a short C program (at the bottom) that I run in a spawned
subprocess and translates the logical name PID (also defined in the
job table), and it works fine.  I even change the logical name while
the program is running and it correctly picks up the new value.

Any clues would be appreciated.

roland
--
Roland B Roberts                 (716) 275-8962         University of Rochester
roberts@uornsrl.bitnet                    Nuclear Structure Research Laboratory
roberts@nsrl31.nsrl.rochester.edu                           271 East River Road
rbr4@uhura.cc.rochester.edu                                 Rochester, NY 14627
--
Fight `Look and Feel' Lawsuits and Software Patents!
Join the League for Programming Freedom, info from: league@prep.ai.mit.edu


Emacs was compiled with the VAXC compiler v3.2-044, and linked under
VMS a5.5 (we haven't yet done the queue upgrade), but the behavior
was present under VMS 5.4-1 as well.

===== Code fragment from Emacs sysdep.c =====
 /* Suspend the Emacs process; give terminal to its superior.  */

sys_suspend ()
{
#ifdef VMS
  /* "Foster" parentage allows emacs to return to a subprocess that attached
   to the current emacs as a cheaper than starting a whole new process. This
   is set up by KEPTEDITOR.COM */

  unsigned long parent_id, foster_parent_id;
  char *fpid_string;
  FILE *debug_file;

  debug_file = fopen ("sys$login:emacs.debug","a+");
  fpid_string = getenv("EMACS_PARENT_PID");
  if (fpid_string != NULL)
    {
      foster_parent_id = strtoul(fpid_string,NULL,16);
      if (foster_parent_id != 0)
	parent_id = foster_parent_id;
      else
	parent_id = getppid ();
      fprintf (debug_file, "%-15s: EMACS_PARENT_ID translated = %s\n",
	       "...", fpid_string);
      fprintf (debug_file,
	       "%17sfoster_parent_id = %08x\n%17sparent_id = %08x\n",
	       "...", foster_parent_id, "...", parent_id);
    }
  else
    parent_id = getppid ();
  fprintf (debug_file, "%17sparent_id = %08x\n", "...", parent_id);
  fclose (debug_file);
  if (parent_id && parent_id != 0xffffffff)
    {
      int oldsig = signal (SIGINT, SIG_IGN);
      int status = LIB$ATTACH (&parent_id) & 1;
      signal (SIGINT, oldsig);
      debug_file = fopen ("sys$login:emacs.debug","a+");
      fprintf (debug_file, "%17slib$attach status = %08x\n", "...", status);
      fclose (debug_file);
      return status;
    }
  return -1;
#else
[...]

The first lines below come from invoking as `emacs -f suspend-emacs'
Note that the first two time I re-enter emacs, everything is fine.
Then I entered mail, did a send/edit and had trouble.  The logical
EMACS_PARENT_PID is defined in the JOB table.

===== Contents of sys$login:emacs.debug after test =====

              ...parent_id = 250000a7
              ...lib$attach status = 00000001
...            : EMACS_PARENT_ID translated = 250000C8
              ...foster_parent_id = 250000c8
              ...parent_id = 250000c8
              ...parent_id = 250000c8
              ...lib$attach status = 00000001
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 000000d4
              ...parent_id = 000000d4
              ...parent_id = 000000d4
              ...lib$attach status = 00000000
...            : EMACS_PARENT_ID translated = 250000D4
              ...foster_parent_id = 250000d4
              ...parent_id = 250000d4
              ...parent_id = 250000d4
              ...lib$attach status = 00000001

This is my test program that behaves fine, even when running in a
subprocess.  Again, PID is defined in the JOB table.
===== Code test.c ====
#include <stdio.h>
#include <stdlib.h>

main ()
{
  unsigned long pid;
  char *pid_string;
  float delay = 5.0;
  
  while (1)
    {
      pid_string = getenv("PID");
      if (pid_string != NULL)
	{
	  printf ("PID translated as %s = ", pid_string);
	  pid = strtoul (pid_string, NULL, 16);
	  printf ("0x%08x = %d\n", pid, pid);
	}
      else
	printf ("PID has no translation\n");
      lib$wait (&delay);
    }
  exit(1);
}
Xref: sparky comp.os.vms:8149 vmsnet.sources.d:304