Bug 432430: NSPR port to Symbian OS, r=nelson
authornelson%bolyard.com
Sun, 22 Mar 2009 02:04:58 +0000
changeset 4081 2d36a1b5e90fe869fa6fc550b33814a3744754fd
parent 4080 0a9a1926b32d3686a509eb5c4b58198fa0556b4f
child 4082 0f57d559c6698c49cd6a46ab5b88ca689e6c74a7
push idunknown
push userunknown
push dateunknown
reviewersnelson
bugs432430
Bug 432430: NSPR port to Symbian OS, r=nelson Patch contributed by Harry Li <harry.li@pagefreedom.org> Modified Files: md/unix/unix.c md/unix/uxproces.c md/unix/uxshm.c misc/prnetdb.c pthreads/ptthread.c
pr/src/md/unix/unix.c
pr/src/md/unix/uxproces.c
pr/src/md/unix/uxshm.c
pr/src/misc/prnetdb.c
pr/src/pthreads/ptthread.c
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -2644,17 +2644,17 @@ PRInt32 _MD_getopenfileinfo64(const PRFi
     PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb);
     if (rv < 0)
         _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
     else if (NULL != info)
         rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
     return rv;
 }
 
-struct _MD_IOVector _md_iovector = { open };
+struct _MD_IOVector _md_iovector;
 
 /*
 ** These implementations are to emulate large file routines on systems that
 ** don't have them. Their goal is to check in case overflow occurs. Otherwise
 ** they will just operate as normal using 32-bit file routines.
 **
 ** The checking might be pre- or post-op, depending on the semantics.
 */
--- a/pr/src/md/unix/uxproces.c
+++ b/pr/src/md/unix/uxproces.c
@@ -276,17 +276,17 @@ ForkAndExec(
            }
        }
     }
 }
 #endif /* VMS */
 
 #ifdef AIX
     process->md.pid = (*pr_wp.forkptr)();
-#elif defined(NTO)
+#elif defined(NTO) || defined(SYMBIAN)
     /*
      * fork() & exec() does not work in a multithreaded process.
      * Use spawn() instead.
      */
     {
         int fd_map[3] = { 0, 1, 2 };
 
         if (attr) {
@@ -307,17 +307,22 @@ ForkAndExec(
                 flags = fcntl(fd_map[2], F_GETFL, 0);
                 if (flags & O_NONBLOCK)
                     fcntl(fd_map[2], F_SETFL, flags & ~O_NONBLOCK);
             }
 
             PR_ASSERT(attr->currentDirectory == NULL);  /* not implemented */
         }
 
+#ifdef SYMBIAN
+        /* In Symbian OS, we use posix_spawn instead of fork() and exec() */
+        posix_spawn(&(process->md.pid), path, NULL, NULL, argv, childEnvp);
+#else
         process->md.pid = spawn(path, 3, fd_map, NULL, argv, childEnvp);
+#endif
 
         if (fd_map[0] != 0)
             close(fd_map[0]);
         if (fd_map[1] != 1)
             close(fd_map[1]);
         if (fd_map[2] != 2)
             close(fd_map[2]);
     }
@@ -334,17 +339,17 @@ ForkAndExec(
     } else if (0 == process->md.pid) {  /* the child process */
         /*
          * If the child process needs to exit, it must call _exit().
          * Do not call exit(), because exit() will flush and close
          * the standard I/O file descriptors, and hence corrupt
          * the parent process's standard I/O data structures.
          */
 
-#if !defined(NTO)
+#if !defined(NTO) && !defined(SYMBIAN)
 #ifdef VMS
        /* OpenVMS has already handled all this above */
 #else
         if (attr) {
             /* the osfd's to redirect stdin, stdout, and stderr to */
             int in_osfd = -1, out_osfd = -1, err_osfd = -1;
 
             if (attr->stdinFd
@@ -975,16 +980,21 @@ done:
     return retVal;
 }  /* _MD_WaitUnixProcess */
 
 PRStatus _MD_KillUnixProcess(PRProcess *process)
 {
     PRErrorCode prerror;
     PRInt32 oserror;
 
+#ifdef SYMBIAN
+    /* In Symbian OS, we can not kill other process with Open C */
+    PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, oserror);
+    return PR_FAILURE;
+#else
     if (kill(process->md.pid, SIGKILL) == 0) {
 	return PR_SUCCESS;
     }
     oserror = errno;
     switch (oserror) {
         case EPERM:
 	    prerror = PR_NO_ACCESS_RIGHTS_ERROR;
 	    break;
@@ -992,9 +1002,10 @@ PRStatus _MD_KillUnixProcess(PRProcess *
 	    prerror = PR_INVALID_ARGUMENT_ERROR;
 	    break;
         default:
 	    prerror = PR_UNKNOWN_ERROR;
 	    break;
     }
     PR_SetError(prerror, oserror);
     return PR_FAILURE;
+#endif
 }  /* _MD_KillUnixProcess */
--- a/pr/src/md/unix/uxshm.c
+++ b/pr/src/md/unix/uxshm.c
@@ -258,17 +258,22 @@ extern PRStatus _MD_DeleteSharedMemory( 
     if ( -1 == key )
     {
         rc = PR_FAILURE;
         _PR_MD_MAP_DEFAULT_ERROR( errno );
         PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, 
             ("_MD_DeleteSharedMemory(): ftok() failed on name: %s", ipcname));
     }
 
+#ifdef SYMBIAN
+    /* In Symbian OS the system imposed minimum is 1 byte, instead of ZERO */
+    id = shmget( key, 1, 0 );
+#else
     id = shmget( key, 0, 0 );
+#endif
     if ( -1 == id ) {
         _PR_MD_MAP_DEFAULT_ERROR( errno );
         PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, 
             ("_MD_DeleteSharedMemory(): shmget() failed, errno: %d", errno));
         return(PR_FAILURE);
     }
 
     urc = shmctl( id, IPC_RMID, NULL );
@@ -510,17 +515,22 @@ extern PRFileMap* _md_OpenAnonFileMap(
     PRInt64     size64; /* 64-bit version of 'size' */
 
     /*
     ** generate a filename from input and runtime environment
     ** open the file, unlink the file.
     ** make maxTries number of attempts at uniqueness in the filename
     */
     for ( incr = 0; incr < maxTries ; incr++ ) {
-        genName = PR_smprintf( "%s/.NSPR-AFM-%d-%p.%d", 
+#if defined(SYMBIAN)
+#define NSPR_AFM_FILENAME "%s\\NSPR-AFM-%d-%p.%d"
+#else
+#define NSPR_AFM_FILENAME "%s/.NSPR-AFM-%d-%p.%d"
+#endif
+        genName = PR_smprintf( NSPR_AFM_FILENAME,
             dirName, (int) pid, tid, incr );
         if ( NULL == genName ) {
             PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
                 ("_md_OpenAnonFileMap(): PR_snprintf(): failed, generating filename"));
             goto Finished;
         }
         
         /* create the file */
@@ -544,17 +554,23 @@ extern PRFileMap* _md_OpenAnonFileMap(
     if ( incr == maxTries ) {
         PR_ASSERT( -1 == osfd );
         PR_ASSERT( EEXIST == errno );
         _PR_MD_MAP_OPEN_ERROR( errno );
         goto Finished;
     }
 
     urc = unlink( genName );
+#if defined(SYMBIAN) && defined(__WINS__)
+    /* If it is being used by the system or another process, Symbian OS 
+     * Emulator(WINS) considers this an error. */
+    if ( -1 == urc && EACCES != errno ) {
+#else
     if ( -1 == urc ) {
+#endif
         _PR_MD_MAP_UNLINK_ERROR( errno );
         PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
             ("_md_OpenAnonFileMap(): failed on unlink(), errno: %d", errno));
         PR_smprintf_free( genName );
         close( osfd );
         goto Finished;        
     }
     PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -591,16 +591,35 @@ static PRStatus CopyHostent(
 		} else {
 			memcpy(to->h_addr_list[na], *ap, to->h_length);
 		}
 	}
 	to->h_addr_list[na] = 0;
 	return PR_SUCCESS;
 }
 
+#ifdef SYMBIAN
+/* Set p_aliases by hand because Symbian's getprotobyname() returns NULL. */
+static void AssignAliases(struct protoent *Protoent, char** aliases)
+{
+    if (NULL == Protoent->p_aliases) {
+        if (0 == strcmp(Protoent->p_name, "ip"))
+            aliases[0] = "IP";
+        else if (0 == strcmp(Protoent->p_name, "tcp"))
+            aliases[0] = "TCP";
+        else if (0 == strcmp(Protoent->p_name, "udp"))
+            aliases[0] = "UDP";
+        else
+            aliases[0] = "UNKNOWN";
+        aliases[1] = NULL;
+        Protoent->p_aliases = aliases;
+    }
+}
+#endif
+
 #if !defined(_PR_HAVE_GETPROTO_R)
 /*
 ** Copy a protoent, and all of the memory that it refers to into
 ** (hopefully) stacked buffers.
 */
 static PRStatus CopyProtoent(
     struct protoent *from, char *buf, PRIntn bufsize, PRProtoEnt *to)
 {
@@ -1248,16 +1267,20 @@ PR_IMPLEMENT(PRStatus) PR_GetProtoByName
 		staticBuf = getprotobyname_r(name);
 		if (NULL == staticBuf)
 		{
 		    rv = PR_FAILURE;
 		    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
         }
 		else
 		{
+#if defined(SYMBIAN)
+			char* aliases[2];
+			AssignAliases(staticBuf, aliases);
+#endif
 			rv = CopyProtoent(staticBuf, buffer, buflen, result);
 			if (PR_FAILURE == rv)
 			    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
         }
 		PR_Unlock(_getproto_lock);
 	}
 #endif  /* all that */
     return rv;
@@ -1328,16 +1351,20 @@ PR_IMPLEMENT(PRStatus) PR_GetProtoByNumb
 		staticBuf = getprotobynumber_r(number);
 		if (NULL == staticBuf)
 		{
 		    rv = PR_FAILURE;
 		    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
         }
 		else
 		{
+#if defined(SYMBIAN)
+			char* aliases[2];
+			AssignAliases(staticBuf, aliases);
+#endif
 			rv = CopyProtoent(staticBuf, buffer, buflen, result);
 			if (PR_FAILURE == rv)
 			    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
         }
 		PR_Unlock(_getproto_lock);
 	}
 #endif  /* all that crap */
     return rv;
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -1154,16 +1154,17 @@ static void null_signal_handler(PRIntn s
 
 /*
  * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which
  * conflict with the use of these two signals in our GC support.
  * So we don't know how to support GC on Linux pthreads.
  */
 static void init_pthread_gc_support(void)
 {
+#ifndef SYMBIAN
     PRIntn rv;
 
 #if defined(_PR_DCETHREADS)
 	rv = sigemptyset(&javagc_vtalarm_sigmask);
     PR_ASSERT(0 == rv);
 	rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM);
     PR_ASSERT(0 == rv);
 #else  /* defined(_PR_DCETHREADS) */
@@ -1190,16 +1191,17 @@ static void init_pthread_gc_support(void
 	    sigact_null.sa_handler = null_signal_handler;
 	    sigact_null.sa_flags = SA_RESTART;
 	    sigemptyset (&sigact_null.sa_mask);
         rv = sigaction (SIGUSR1, &sigact_null, NULL);
 	    PR_ASSERT(0 ==rv); 
     }
 #endif  /* defined(PT_NO_SIGTIMEDWAIT) */
 #endif /* defined(_PR_DCETHREADS) */
+#endif /* SYMBIAN */
 }
 
 PR_IMPLEMENT(void) PR_SetThreadGCAble(void)
 {
     PR_Lock(pt_book.ml);
 	PR_GetCurrentThread()->state |= PT_THREAD_GCABLE;
     PR_Unlock(pt_book.ml);
 }
@@ -1341,17 +1343,18 @@ static void suspend_signal_handler(PRInt
 	 * now, block current thread
 	 */
 #if defined(PT_NO_SIGTIMEDWAIT)
 	pthread_cond_signal(&me->suspendResumeCV);
 	while (me->suspend & PT_THREAD_SUSPENDED)
 	{
 #if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
     && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) \
-    && !defined(DARWIN) && !defined(RISCOS) /*XXX*/
+    && !defined(DARWIN) && !defined(RISCOS) \
+    && !defined(SYMBIAN) /*XXX*/
         PRIntn rv;
 	    sigwait(&sigwait_set, &rv);
 #endif
 	}
 	me->suspend |= PT_THREAD_RESUMED;
 	pthread_cond_signal(&me->suspendResumeCV);
 #else /* defined(PT_NO_SIGTIMEDWAIT) */
 	while (me->suspend & PT_THREAD_SUSPENDED)
@@ -1387,16 +1390,19 @@ static void pt_SuspendSet(PRThread *thre
 
     PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0);
 
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
 	   ("doing pthread_kill in pt_SuspendSet thred %p tid = %X\n",
 	   thred, thred->id));
 #if defined(VMS)
     rv = thread_suspend(thred);
+#elif defined(SYMBIAN)
+    /* All signal group functions are not implemented in Symbian OS */
+    rv = 0;
 #else
     rv = pthread_kill (thred->id, SIGUSR2);
 #endif
     PR_ASSERT(0 == rv);
 }
 
 static void pt_SuspendTest(PRThread *thred)
 {
@@ -1443,16 +1449,18 @@ static void pt_ResumeSet(PRThread *thred
     PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED);
 
 
     thred->suspend &= ~PT_THREAD_SUSPENDED;
 
 #if defined(PT_NO_SIGTIMEDWAIT)
 #if defined(VMS)
 	thread_resume(thred);
+#elif defined(SYMBIAN) 
+	/* All signal group functions are not implemented in Symbian OS */
 #else
 	pthread_kill(thred->id, SIGUSR1);
 #endif
 #endif
 
 }  /* pt_ResumeSet */
 
 static void pt_ResumeTest(PRThread *thred)