Bug 1420407, land NSPR 4.18.1 beta1 (r=me) and remove local NSPR patch that's no longer necessary (r=dragana)
☠☠ backed out by b97b62055f10 ☠ ☠
authorKai Engert <kaie@kuix.de>
Mon, 27 Nov 2017 21:01:35 +0100
changeset 393900 f7f814a5a9577b545036f9be69aeb5293d8feda0
parent 393899 afefcc7ecca06203a0ea46f4f6949ab509911c93
child 393901 4e5b62d139a83ea164cb4ae52e3a5b60de732a1f
push id32985
push usercbrindusan@mozilla.com
push dateTue, 28 Nov 2017 09:51:26 +0000
treeherdermozilla-central@5b33b070378a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme, dragana
bugs1420407
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1420407, land NSPR 4.18.1 beta1 (r=me) and remove local NSPR patch that's no longer necessary (r=dragana) UPGRADE_NSPR_RELEASE
nsprpub/TAG-INFO
nsprpub/config/prdepend.h
nsprpub/configure
nsprpub/configure.in
nsprpub/patches/README.TXT
nsprpub/patches/bug1399100-temporary.patch
nsprpub/pr/include/prinit.h
nsprpub/pr/include/private/pprio.h
nsprpub/pr/include/private/primpl.h
nsprpub/pr/src/io/prio.c
nsprpub/pr/src/io/prsocket.c
nsprpub/pr/src/md/windows/w95sock.c
nsprpub/pr/src/md/windows/w95thred.c
nsprpub/pr/src/nspr.def
nsprpub/pr/src/pthreads/ptio.c
nsprpub/pr/src/pthreads/ptthread.c
nsprpub/pr/tests/vercheck.c
--- a/nsprpub/TAG-INFO
+++ b/nsprpub/TAG-INFO
@@ -1,1 +1,1 @@
-NSPR_4_17_RTM
+NSPR_4_18_BETA1
--- a/nsprpub/config/prdepend.h
+++ b/nsprpub/config/prdepend.h
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/nsprpub/configure
+++ b/nsprpub/configure
@@ -2483,17 +2483,17 @@ case $target_os in *\ *) target_os=`echo
 # The aliases save the names the user supplied, while $host etc.
 # will get canonicalized.
 test -n "$target_alias" &&
   test "$program_prefix$program_suffix$program_transform_name" = \
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
 
 MOD_MAJOR_VERSION=4
-MOD_MINOR_VERSION=17
+MOD_MINOR_VERSION=18
 MOD_PATCH_VERSION=0
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_X32=
--- a/nsprpub/configure.in
+++ b/nsprpub/configure.in
@@ -10,17 +10,17 @@ AC_CONFIG_SRCDIR([pr/include/nspr.h])
 
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
 AC_CANONICAL_TARGET
 
 dnl ========================================================
 dnl = Defaults
 dnl ========================================================
 MOD_MAJOR_VERSION=4
-MOD_MINOR_VERSION=17
+MOD_MINOR_VERSION=18
 MOD_PATCH_VERSION=0
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_X32=
deleted file mode 100644
--- a/nsprpub/patches/README.TXT
+++ /dev/null
@@ -1,9 +0,0 @@
-bug1399100-temporary.patch :
-  This is a temporary patch as described in
-    https://bugzilla.mozilla.org/show_bug.cgi?id=1399100
-  It is temporarily necessary because of the changes in
-    https://bugzilla.mozilla.org/show_bug.cgi?id=1384633
-  The patch should be re-applied during the Firefox 57 release cycle,
-  if other changes to NSPR are necessary during the lifetime of Firefox 57.
-  The temporary API will be removed for Firefox 58, as agreed in
-    https://bugzilla.mozilla.org/show_bug.cgi?id=1394808
deleted file mode 100644
--- a/nsprpub/patches/bug1399100-temporary.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/nsprpub/pr/src/nspr.def b/nsprpub/pr/src/nspr.def
---- a/nsprpub/pr/src/nspr.def
-+++ b/nsprpub/pr/src/nspr.def
-@@ -457,8 +457,12 @@ EXPORTS ;-
- ;+} NSPR_4.9.2;
- ;+# Function PR_DuplicateEnvironment had been added in NSPR 4.10.9,
- ;+# but we neglected to add it to nspr.def until NSPR 4.12
- ;+NSPR_4.12 {
- ;+      global:
- 		PR_DuplicateEnvironment;
- 		PR_GetEnvSecure;
- ;+} NSPR_4.10.3;
-+;+NSPR_4.17_fork {
-+;+      global:
-+		PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle;
-+;+} NSPR_4.16;
--- a/nsprpub/pr/include/prinit.h
+++ b/nsprpub/pr/include/prinit.h
@@ -26,21 +26,21 @@ PR_BEGIN_EXTERN_C
 /*
 ** NSPR's version is used to determine the likelihood that the version you
 ** used to build your component is anywhere close to being compatible with
 ** what is in the underlying library.
 **
 ** The format of the version string is
 **     "<major version>.<minor version>[.<patch level>] [<Beta>]"
 */
-#define PR_VERSION  "4.17"
+#define PR_VERSION  "4.18 Beta"
 #define PR_VMAJOR   4
-#define PR_VMINOR   17
+#define PR_VMINOR   18
 #define PR_VPATCH   0
-#define PR_BETA     PR_FALSE
+#define PR_BETA     PR_TRUE
 
 /*
 ** PRVersionCheck
 **
 ** The basic signature of the function that is called to provide version
 ** checking. The result will be a boolean that indicates the likelihood
 ** that the underling library will perform as the caller expects.
 **
--- a/nsprpub/pr/include/private/pprio.h
+++ b/nsprpub/pr/include/private/pprio.h
@@ -232,25 +232,11 @@ NSPR_API(void) PR_NTFast_UpdateAcceptCon
 ** DESCRIPTION:
 **    Cancel IO operations on fd.
 */
 NSPR_API(PRStatus) PR_NT_CancelIo(PRFileDesc *fd);
 
 
 #endif /* WIN32 */
 
-/* FUNCTION: PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle
-** DESCRIPTION:
-** This function will be available only in nspr version 4.17
-** This functionality is only available on windows. Some windows operation use
-** asynchronous (call overlapped) io. One of them is ConnectEx. NSPR uses
-** ConnectEx for enabling TCP Fast Open.
-** This function returns an OVERLAPPED structure associated with ConnectEx call.
-** If ConnectEx has not been called or the io has already finished, the
-** function will return PR_INVALID_ARGUMENT_ERROR.
-** PRFileDesc continues to be owner of the structure and the structure must not
-** be destroyed.
-*/
-NSPR_API(PRStatus) PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle(PRFileDesc *fd, void **ol);
-
 PR_END_EXTERN_C
 
 #endif /* pprio_h___ */
--- a/nsprpub/pr/include/private/primpl.h
+++ b/nsprpub/pr/include/private/primpl.h
@@ -2160,11 +2160,23 @@ typedef struct _ConnectListNode {
 } ConnectListNode;
 
 extern ConnectListNode connectList[64];
 
 extern PRUint32 connectCount;
 
 #endif /* XP_BEOS */
 
+#if defined(_WIN64) && defined(WIN95)
+typedef struct _PRFileDescList {
+  PRFileDesc *fd;
+  struct _PRFileDescList *next;
+} PRFileDescList;
+
+extern PRLock *_fd_waiting_for_overlapped_done_lock;
+extern PRFileDescList *_fd_waiting_for_overlapped_done;
+extern void CheckOverlappedPendingSocketsAreDone();
+#endif
+
+
 PR_END_EXTERN_C
 
 #endif /* primpl_h___ */
--- a/nsprpub/pr/src/io/prio.c
+++ b/nsprpub/pr/src/io/prio.c
@@ -132,21 +132,92 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDe
 }
 
 PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc *fd)
 {
     PR_ASSERT(fd);
     _PR_Putfd(fd);
 }
 
+#if defined(_WIN64) && defined(WIN95)
+
+PRFileDescList *_fd_waiting_for_overlapped_done = NULL;
+PRLock *_fd_waiting_for_overlapped_done_lock = NULL;
+
+void CheckOverlappedPendingSocketsAreDone()
+{
+  if (!_fd_waiting_for_overlapped_done_lock ||
+      !_fd_waiting_for_overlapped_done) {
+    return;
+  }
+
+  PR_Lock(_fd_waiting_for_overlapped_done_lock);
+
+  PRFileDescList *cur = _fd_waiting_for_overlapped_done;
+  PRFileDescList *previous = NULL;
+  while (cur) {
+    PR_ASSERT(cur->fd->secret->overlappedActive);
+    PRFileDesc *fd = cur->fd;
+    DWORD rvSent;
+    if (GetOverlappedResult((HANDLE)fd->secret->md.osfd, &fd->secret->ol, &rvSent, FALSE) == TRUE) {
+      fd->secret->overlappedActive = PR_FALSE;
+      PR_LOG(_pr_io_lm, PR_LOG_MIN,
+             ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult succeeded\n"));
+    } else {
+      DWORD err = WSAGetLastError();
+      PR_LOG(_pr_io_lm, PR_LOG_MIN,
+             ("CheckOverlappedPendingSocketsAreDone GetOverlappedResult failed %d\n", err));
+      if (err != ERROR_IO_INCOMPLETE) {
+        fd->secret->overlappedActive = PR_FALSE;
+      }
+    }
+
+    if (!fd->secret->overlappedActive) {
+
+      _PR_MD_CLOSE_SOCKET(fd->secret->md.osfd);
+      fd->secret->state = _PR_FILEDESC_CLOSED;
+#ifdef _PR_HAVE_PEEK_BUFFER
+      if (fd->secret->peekBuffer) {
+        PR_ASSERT(fd->secret->peekBufSize > 0);
+        PR_DELETE(fd->secret->peekBuffer);
+        fd->secret->peekBufSize = 0;
+        fd->secret->peekBytes = 0;
+      }
+#endif
+
+      PR_FreeFileDesc(fd);
+
+      if (previous) {
+        previous->next = cur->next;
+      } else {
+        _fd_waiting_for_overlapped_done = cur->next;
+      }
+      PRFileDescList *del = cur;
+      cur = cur->next;
+      PR_Free(del);
+    } else {
+      previous = cur;
+      cur = cur->next;
+    }
+  }
+
+  PR_Unlock(_fd_waiting_for_overlapped_done_lock);
+}
+#endif
+
 /*
 ** Wait for some i/o to finish on one or more more poll descriptors.
 */
 PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
 {
+#if defined(_WIN64) && defined(WIN95)
+  // For each iteration check if TFO overlapped IOs are down.
+  CheckOverlappedPendingSocketsAreDone();
+#endif
+
 	return(_PR_MD_PR_POLL(pds, npds, timeout));
 }
 
 /*
 ** Set the inheritance attribute of a file descriptor.
 */
 PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
     PRFileDesc *fd,
--- a/nsprpub/pr/src/io/prsocket.c
+++ b/nsprpub/pr/src/io/prsocket.c
@@ -732,16 +732,66 @@ static PRStatus PR_CALLBACK SocketClose(
 	if (!fd || !fd->secret
 			|| (fd->secret->state != _PR_FILEDESC_OPEN
 			&& fd->secret->state != _PR_FILEDESC_CLOSED)) {
 		PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
 		return PR_FAILURE;
 	}
 
 	if (fd->secret->state == _PR_FILEDESC_OPEN) {
+#if defined(_WIN64) && defined(WIN95)
+    /* TCP Fast Open on Windows must use ConnectEx, which uses overlapped
+     * input/output. Before closing such a socket we must cancelIO.
+     */
+    if (fd->secret->overlappedActive) {
+      PR_ASSERT(fd->secret->nonblocking);
+      if (CancelIo((HANDLE) fd->secret->md.osfd) == TRUE) {
+        PR_LOG(_pr_io_lm, PR_LOG_MIN,
+               ("SocketClose - CancelIo succeeded\n"));
+      } else {
+        DWORD err = WSAGetLastError();
+        PR_LOG(_pr_io_lm, PR_LOG_MIN,
+               ("SocketClose - CancelIo failed err=%x\n", err));
+      }
+
+      DWORD rvSent;
+      if (GetOverlappedResult((HANDLE)fd->secret->md.osfd, &fd->secret->ol, &rvSent, FALSE) == TRUE) {
+        fd->secret->overlappedActive = PR_FALSE;
+        PR_LOG(_pr_io_lm, PR_LOG_MIN,
+               ("SocketClose GetOverlappedResult succeeded\n"));
+      } else {
+        DWORD err = WSAGetLastError();
+        PR_LOG(_pr_io_lm, PR_LOG_MIN,
+               ("SocketClose GetOverlappedResult failed %d\n", err));
+        if (err != ERROR_IO_INCOMPLETE) {
+          _PR_MD_MAP_CONNECT_ERROR(err);
+          fd->secret->overlappedActive = PR_FALSE;
+        }
+      }
+    }
+
+    if (fd->secret->overlappedActive &&
+        _fd_waiting_for_overlapped_done_lock) {
+      // Put osfd into the list to be checked later.
+      PRFileDescList *forWaiting = PR_NEW(PRFileDescList);
+      if (!forWaiting) {
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return PR_FAILURE;
+      }
+      forWaiting->fd = fd;
+
+      PR_Lock(_fd_waiting_for_overlapped_done_lock);
+      forWaiting->next = _fd_waiting_for_overlapped_done;
+      _fd_waiting_for_overlapped_done = forWaiting;
+      PR_Unlock(_fd_waiting_for_overlapped_done_lock);
+
+      return PR_SUCCESS;
+    }
+#endif
+
 		if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) {
 			return PR_FAILURE;
 		}
 		fd->secret->state = _PR_FILEDESC_CLOSED;
 	}
 
 #ifdef _PR_HAVE_PEEK_BUFFER
 	if (fd->secret->peekBuffer) {
@@ -1679,43 +1729,16 @@ PR_FileDesc2NativeHandle(PRFileDesc *fd)
 
 PR_IMPLEMENT(void)
 PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PROsfd handle)
 {
 	if (fd)
 		fd->secret->md.osfd = handle;
 }
 
-/* Expose OVERLAPPED if present. OVERLAPPED is implemented only on WIN95. */
-PR_IMPLEMENT(PRStatus)
-PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle(PRFileDesc *fd, void **ol)
-{
-#if defined(_WIN64) && defined(WIN95)
-    *ol = NULL;
-    if (fd) {
-        fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
-    }
-    if (!fd) {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return PR_FAILURE;
-    }
-
-    if (!fd->secret->overlappedActive) {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return PR_FAILURE;
-    }
-
-    *ol = &fd->secret->ol;
-    return PR_SUCCESS;
-#else
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return PR_FAILURE;
-#endif
-}
-
 /*
 ** Select compatibility
 **
 */
 
 PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
 {
 	memset(set, 0, sizeof(PR_fd_set));
--- a/nsprpub/pr/src/md/windows/w95sock.c
+++ b/nsprpub/pr/src/md/windows/w95sock.c
@@ -377,16 +377,21 @@ static PRStatus PR_CALLBACK _pr_set_conn
     rc = closesocket(sock);
     return PR_SUCCESS;
 }
 
 PRInt32
 _PR_MD_TCPSENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
                  const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
 {
+    if (!_fd_waiting_for_overlapped_done_lock) {
+        PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+        return PR_FAILURE;
+    }
+
     if (PR_CallOnce(&_pr_has_connectex_once, _pr_set_connectex) != PR_SUCCESS) {
         PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
         return PR_FAILURE;
     }
 
     if (_pr_win_connectex == NULL) {
         PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
         return PR_FAILURE;
--- a/nsprpub/pr/src/md/windows/w95thred.c
+++ b/nsprpub/pr/src/md/windows/w95thred.c
@@ -30,31 +30,58 @@ int                           _pr_intsOf
 void
 _PR_MD_EARLY_INIT()
 {
 #ifndef _PR_USE_STATIC_TLS
     _pr_currentThreadIndex = TlsAlloc();
     _pr_lastThreadIndex = TlsAlloc();
     _pr_currentCPUIndex = TlsAlloc();
 #endif
+
+#if defined(_WIN64) && defined(WIN95)
+    _fd_waiting_for_overlapped_done_lock = PR_NewLock();
+#endif
 }
 
 void _PR_MD_CLEANUP_BEFORE_EXIT(void)
 {
     _PR_NT_FreeSids();
 
     _PR_MD_CleanupSockets();
 
     WSACleanup();
 
 #ifndef _PR_USE_STATIC_TLS
     TlsFree(_pr_currentThreadIndex);
     TlsFree(_pr_lastThreadIndex);
     TlsFree(_pr_currentCPUIndex);
 #endif
+
+#if defined(_WIN64) && defined(WIN95)
+    // For each iteration check if TFO overlapped IOs are down.
+    if (_fd_waiting_for_overlapped_done_lock) {
+        PRIntervalTime delay = PR_MillisecondsToInterval(1000);
+        PRFileDescList *cur;
+        do {
+            CheckOverlappedPendingSocketsAreDone();
+
+            PR_Lock(_fd_waiting_for_overlapped_done_lock);
+            cur = _fd_waiting_for_overlapped_done;
+            PR_Unlock(_fd_waiting_for_overlapped_done_lock);
+#if define DO_NOT_WAIT_FOR_CONNECT_OVERLAPPED_OPERATIONS
+            cur = NULL;
+#endif
+            if (cur) {
+                PR_Sleep(delay); // wait another 1s.
+            }
+        } while (cur);
+
+        PR_DestroyLock(_fd_waiting_for_overlapped_done_lock);
+    }
+#endif
 }
 
 PRStatus
 _PR_MD_INIT_THREAD(PRThread *thread)
 {
     if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
         /*
         ** Warning:
--- a/nsprpub/pr/src/nspr.def
+++ b/nsprpub/pr/src/nspr.def
@@ -457,12 +457,8 @@ EXPORTS ;-
 ;+} NSPR_4.9.2;
 ;+# Function PR_DuplicateEnvironment had been added in NSPR 4.10.9,
 ;+# but we neglected to add it to nspr.def until NSPR 4.12
 ;+NSPR_4.12 {
 ;+      global:
 		PR_DuplicateEnvironment;
 		PR_GetEnvSecure;
 ;+} NSPR_4.10.3;
-;+NSPR_4.17_fork {
-;+      global:
-		PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle;
-;+} NSPR_4.16;
--- a/nsprpub/pr/src/pthreads/ptio.c
+++ b/nsprpub/pr/src/pthreads/ptio.c
@@ -4739,24 +4739,16 @@ PR_IMPLEMENT(PRInt32) PR_FileDesc2Native
     PRInt32 osfd = -1;
     bottom = (NULL == bottom) ?
         NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
     if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     else osfd = bottom->secret->md.osfd;
     return osfd;
 }  /* PR_FileDesc2NativeHandle */
 
-/* Expose OVERLAPPED if present. OVERLAPPED is implemented only on WIN95. */
-PR_IMPLEMENT(PRStatus)
-PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle(PRFileDesc *fd, void **ol)
-{
-    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
-    return PR_FAILURE;
-}
-
 PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd,
     PRInt32 handle)
 {
     if (fd) fd->secret->md.osfd = handle;
 }  /*  PR_ChangeFileDescNativeHandle*/
 
 PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
 {
--- a/nsprpub/pr/src/pthreads/ptthread.c
+++ b/nsprpub/pr/src/pthreads/ptthread.c
@@ -1059,16 +1059,21 @@ void PR_HPUX10xInit(shl_t handle, int lo
 }
 #endif
 #elif defined(AIX)
 /* Need to use the -binitfini::_PR_Fini linker option. */
 #endif
 
 void _PR_Fini(void)
 {
+    /* We disable the cleanup code on Mac OSX, see bug 1399746.
+     * The .dylib containing NSPR can get unloaded, and _PR_Fini called,
+     * and other code calling NSPR functions can get executed afterwards.
+    */
+#ifndef DARWIN
     void *thred;
     int rv;
 
     if (!_pr_initialized) {
         /* Either NSPR was never successfully initialized or 
          * PR_Cleanup has been called already. */
         if (pt_book.keyCreated)
         {
@@ -1090,16 +1095,17 @@ void _PR_Fini(void)
         rv = pthread_setspecific(pt_book.key, NULL);
         PR_ASSERT(0 == rv);
     }
     rv = pthread_key_delete(pt_book.key);
     PR_ASSERT(0 == rv);
     pt_book.keyCreated = PR_FALSE;
     /* TODO: free other resources used by NSPR */
     /* _pr_initialized = PR_FALSE; */
+#endif
 }  /* _PR_Fini */
 
 PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
 {
     PRThread *me = PR_GetCurrentThread();
     int rv;
     PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
     PR_ASSERT(me->state & PT_THREAD_PRIMORD);
--- a/nsprpub/pr/tests/vercheck.c
+++ b/nsprpub/pr/tests/vercheck.c
@@ -35,34 +35,34 @@ static char *compatible_version[] = {
     "4.7.6",
     "4.8", "4.8.1", "4.8.2", "4.8.3", "4.8.4", "4.8.5",
     "4.8.6", "4.8.7", "4.8.8", "4.8.9",
     "4.9", "4.9.1", "4.9.2", "4.9.3", "4.9.4", "4.9.5",
     "4.9.6",
     "4.10", "4.10.1", "4.10.2", "4.10.3", "4.10.4",
     "4.10.5", "4.10.6", "4.10.7", "4.10.8", "4.10.9",
     "4.10.10", "4.11", "4.12", "4.13", "4.14", "4.15",
-    "4.16",
+    "4.16", "4.17",
     PR_VERSION
 };
 
 /*
  * This release is not backward compatible with the old
  * NSPR 2.1 and 3.x releases.
  *
  * Any release is incompatible with future releases and
  * patches.
  */
 static char *incompatible_version[] = {
     "2.1 19980529",
     "3.0", "3.0.1",
     "3.1", "3.1.1", "3.1.2", "3.1.3",
     "3.5", "3.5.1",
-    "4.17.1",
-    "4.18", "4.18.1",
+    "4.18.1",
+    "4.19", "4.19.1",
     "10.0", "11.1", "12.14.20"
 };
 
 int main(int argc, char **argv)
 {
     int idx;
     int num_compatible = sizeof(compatible_version) / sizeof(char *);
     int num_incompatible = sizeof(incompatible_version) / sizeof(char *);