diff --git a/system/core/liblog/logd_write.c b/system/core/liblog/logd_write.c
--- a/system/core/liblog/logd_write.c
+++ b/system/core/liblog/logd_write.c
@@ -201,6 +201,95 @@
     va_list ap;
     char buf[LOG_BUF_SIZE];
 
+    // Implement additional synchronization for statements coming from
+    // libsecgps (libgps) to workaround the Epic's GPS crash when the RIL
+    // processes multiple requests simultaneously.
+    if (tag != NULL && strcmp(tag, "libgps") == 0) {
+        static pthread_mutex_t request_mutex   = PTHREAD_MUTEX_INITIALIZER;
+        static unsigned int    request_depth   = 0;
+        static pthread_cond_t  req_finish_cond = PTHREAD_COND_INITIALIZER;
+
+        if (strcmp(fmt, "%s: new gps req %p cmd %d, idx %d") == 0) {
+            char *func;
+            int   cmd;
+
+            va_start(ap, fmt);
+            func = va_arg(ap, char *);
+                   va_arg(ap, void *);
+            cmd  = va_arg(ap, int);
+            va_end(ap);
+
+            if (strcmp(func, "newGpsRequest") == 0) {
+                // Received a new GPS request.
+
+                __android_log_print(ANDROID_LOG_DEBUG, "liblog",
+                    "newGpsRequest: cmd=%d, request_depth=%u.", cmd, request_depth);
+
+                pthread_mutex_lock(&request_mutex);
+
+                // Don't allow for interleaved requests.  If there's an outstanding
+                // request, defer this request until the first is finished.  Or at least
+                // wait long enough that any outstanding request must have timed out.
+                while (request_depth > 0) {
+                    struct timeval  now;
+                    struct timespec later;
+
+                    __android_log_print(ANDROID_LOG_WARN, "liblog",
+                        "newGpsRequest: cmd=%d, request_depth=%u; deferring.",
+                        cmd, request_depth);
+
+                    // RIL's internal condition variable has a maximum timeout of 4s on an
+                    // xtra_set_data request, so wait 5s here in the event of an error.
+                    gettimeofday(&now, NULL);
+                    later.tv_sec  = now.tv_sec  +    5;
+                    later.tv_nsec = now.tv_usec * 1000;
+
+                    if (pthread_cond_timedwait(&req_finish_cond, &request_mutex, &later) == ETIMEDOUT) {
+                        __android_log_write(ANDROID_LOG_ERROR, "liblog",
+                            "newGpsRequest: pthread_cond_timedwait: ETIMEDOUT.");
+                        break;
+                    }
+                }
+
+                request_depth++;
+                pthread_mutex_unlock(&request_mutex);
+            }
+        } else if (strcmp(fmt, "%s: Left critsec") == 0) {
+            char *func;
+
+            va_start(ap, fmt);
+            func = va_arg(ap, char *);
+            va_end(ap);
+
+            if (strcmp(func, "ril_gps_wakeup") == 0) {
+                // RIL finished processing the current request.
+
+                // NOTE: removeGpsRequest is a more obvious log target, but libsecgps holds
+                // a lock internally and removeGpsRequest doesn't execute while
+                // newGpsRequest is deferred.  Also, "ril_gps_wait_for_ril: (n=0, r=0)"
+                // does not log if the internal pthread_cond_timewait falls through.  Which
+                // leaves "ril_gps_wakeup: Left critsec" as the only remaining choice.
+
+                __android_log_print(ANDROID_LOG_DEBUG, "liblog",
+                    "ril_gps_wakeup: request_depth=%u.", request_depth);
+
+                pthread_mutex_lock(&request_mutex);
+
+                // Wake any deferred requests.
+                if (request_depth > 0) {
+                    request_depth--;
+                    pthread_cond_signal(&req_finish_cond);
+                } else {
+                    // May happen if message isn't logged in some exceptional circumstance.
+                    __android_log_print(ANDROID_LOG_ERROR, "liblog",
+                        "ril_gps_wakeup: request_depth is already 0.");
+                }
+
+                pthread_mutex_unlock(&request_mutex);
+            }
+        }
+    }
+
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
     va_end(ap);
