>>>> "MB" == Martin Buchholz
<martin(a)xemacs.org> writes:
MB> What is the effect? Here's one bug:
MB> with pdump:
MB> (martin@polgar) /usr/local/x/build/mpps/src $ ./xemacs -batch -eval '(message
"%s %s" (make-temp-name "foo") (make-temp-name "foo"))'
MB> fooWdDWXY fooWdDWXY
MB> without pdump:
MB> (martin@polgar) /usr/local/x/build/mps/src $ ./xemacs -batch -eval '(message
"%s %s" (make-temp-name "foo") (make-temp-name "foo"))'
MB> fooXdD_XY fooXdDgqm
The bug with Frunning_temacs_p() still needs to be fixed (I cast a
vote for Olivier to do it), but here's a fix for this specific problem,
with other "improvements".
src/ChangeLog:
2000-03-10 Martin Buchholz <martin(a)xemacs.org>
* emacs.c: Add reinit_vars_of_fileio.
* symsinit.h: Add reinit_vars_of_fileio.
* fileio.c (reinit_vars_of_fileio): New.
* fileio.c (Fmake_temp_name):
Initialize temp_name random number from microseconds to make
collisions even less likely. Initialize always at process startup
time. (make-temp-name) used to return the same file name twice in
a row when PDUMP.
Random stylistic fiddling.
Comment fixes.
tests/ChangeLog:
2000-03-10 Martin Buchholz <martin(a)xemacs.org>
* automated/mule-tests.el: Check that (make-temp-name) returns
unique values.
Index: src/symsinit.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/symsinit.h,v
retrieving revision 1.31.2.22
diff -u -w -r1.31.2.22 symsinit.h
--- symsinit.h 2000/02/05 07:09:02 1.31.2.22
+++ symsinit.h 2000/03/11 00:59:58
@@ -290,6 +290,7 @@
void reinit_vars_of_extents (void);
void vars_of_faces (void);
void vars_of_fileio (void);
+void reinit_vars_of_fileio (void);
void vars_of_filelock (void);
void vars_of_floatfns (void);
void vars_of_font_lock (void);
Index: src/fileio.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/fileio.c,v
retrieving revision 1.51.2.22
diff -u -w -r1.51.2.22 fileio.c
--- fileio.c 2000/03/05 21:55:47 1.51.2.22
+++ fileio.c 2000/03/11 01:00:09
@@ -635,8 +635,10 @@
This implementation is better than what one usually finds in libc.
--hniksic */
+static unsigned int temp_name_rand;
+
DEFUN ("make-temp-name", Fmake_temp_name, 1, 1, 0, /*
-Generate temporary file name starting with PREFIX.
+Generate a temporary file name starting with PREFIX.
The Emacs process number forms part of the result, so there is no
danger of generating a name being used by another process.
@@ -645,8 +647,9 @@
be an absolute file name.
*/
(prefix))
+{
+ static const char tbl[64] =
{
- static char tbl[64] = {
'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X',
@@ -654,13 +657,12 @@
'g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3',
-
'4','5','6','7','8','9','-','_'
};
- static unsigned count, count_initialized_p;
+
'4','5','6','7','8','9','-','_'
+ };
Lisp_Object val;
Bytecount len;
Bufbyte *p, *data;
- unsigned pid;
CHECK_STRING (prefix);
@@ -686,40 +688,33 @@
/* VAL is created by adding 6 characters to PREFIX. The first three
are the PID of this process, in base 64, and the second three are
- incremented if the file already exists. This ensures 262144
- unique file names per PID per PREFIX. */
+ a pseudo-random number seeded from process startup time. This
+ ensures 262144 unique file names per PID per PREFIX per machine. */
- pid = (unsigned)getpid ();
- *p++ = tbl[pid & 63], pid >>= 6;
- *p++ = tbl[pid & 63], pid >>= 6;
- *p++ = tbl[pid & 63], pid >>= 6;
+ {
+ unsigned int pid = (unsigned int) getpid ();
+ *p++ = tbl[(pid >> 0) & 63];
+ *p++ = tbl[(pid >> 6) & 63];
+ *p++ = tbl[(pid >> 12) & 63];
+ }
/* Here we try to minimize useless stat'ing when this function is
invoked many times successively with the same PREFIX. We achieve
- this by initializing count to a random value, and incrementing it
- afterwards. */
- if (!count_initialized_p)
- {
- count = (unsigned)time (NULL);
- /* Dumping temacs with a non-zero count_initialized_p wouldn't
- make much sense. */
- if (NILP (Frunning_temacs_p ()))
- count_initialized_p = 1;
- }
+ this by using a very pseudo-random number generator to generate
+ file names unique to this process, with a very long cycle. */
while (1)
{
struct stat ignored;
- unsigned num = count;
- p[0] = tbl[num & 63], num >>= 6;
- p[1] = tbl[num & 63], num >>= 6;
- p[2] = tbl[num & 63], num >>= 6;
+ p[0] = tbl[(temp_name_rand >> 0) & 63];
+ p[1] = tbl[(temp_name_rand >> 6) & 63];
+ p[2] = tbl[(temp_name_rand >> 12) & 63];
/* Poor man's congruential RN generator. Replace with ++count
for debugging. */
- count += 25229;
- count %= 225307;
+ temp_name_rand += 25229;
+ temp_name_rand %= 225307;
QUIT;
@@ -1846,7 +1841,7 @@
{
return Fsignal (Qfile_error,
list3 (build_translated_string ("Creating directory"),
- build_translated_string ("pathame too long"),
+ build_translated_string ("pathname too long"),
dirname_));
}
strncpy (dir, (char *) XSTRING_DATA (dirname_),
@@ -4321,4 +4316,26 @@
#else
Vdirectory_sep_char = make_char ('/');
#endif
+
+ reinit_vars_of_fileio ();
+}
+
+void
+reinit_vars_of_fileio (void)
+{
+ /* We want temp_name_rand to be initialized to a value likely to be
+ unique to the process, not to the executable. The danger is that
+ two different XEmacs processes using the same binary on different
+ machines creating temp files in the same directory will be
+ unlucky enough to have the same pid. If we randomize using
+ process startup time, then in practice they will be unlikely to
+ collide. We use the microseconds field so that scripts that start
+ simultaneous XEmacs processes on multiple machines will have less
+ chance of collision. */
+ {
+ EMACS_TIME thyme;
+
+ EMACS_GET_TIME (thyme);
+ temp_name_rand = (unsigned int) (EMACS_SECS (thyme) ^ EMACS_USECS (thyme));
+ }
}
Index: src/emacs.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/emacs.c,v
retrieving revision 1.82.2.53
diff -u -w -r1.82.2.53 emacs.c
--- emacs.c 2000/03/06 20:57:45 1.82.2.53
+++ emacs.c 2000/03/11 01:00:16
@@ -1264,7 +1264,7 @@
using a global variable that has been initialized
earlier on in the same function
- Any of the object-creating functions on alloc.c: e.g.
+ Any of the object-creating functions in alloc.c: e.g.
make_pure_*()
make_string()
@@ -1680,6 +1680,7 @@
reinit_vars_of_event_stream ();
reinit_vars_of_events ();
reinit_vars_of_extents ();
+ reinit_vars_of_fileio ();
reinit_vars_of_font_lock ();
reinit_vars_of_glyphs ();
reinit_vars_of_glyphs_widget ();
Index: tests/automated/mule-tests.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/tests/automated/Attic/mule-tests.el,v
retrieving revision 1.1.2.6
diff -u -w -r1.1.2.6 mule-tests.el
--- mule-tests.el 2000/02/19 09:25:03 1.1.2.6
+++ mule-tests.el 2000/03/11 01:00:17
@@ -299,6 +299,7 @@
(file-name-coding-system 'iso-8859-2))
;; This is how you suppress output from `message', called by `write-region'
(flet ((append-message (&rest args) ()))
+ (Assert (not (equal name1 name2)))
(Assert (not (file-exists-p name1)))
(write-region (point-min) (point-max) name1)
(Assert (file-exists-p name1))