diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index d7cd81cf58823de1791c4a195af33a4ad994052a..dd2eec6d2f9efdc906c45766e51645357e03d321 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1769,6 +1769,7 @@ add_executable(lte-softmodem
   ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
   ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
   ${OPENAIR_DIR}/common/utils/utils.c
+  ${OPENAIR_DIR}/common/utils/system.c
   ${GTPU_need_ITTI}
   ${HW_SOURCE}
   ${TRANSPORT_SOURCE}
@@ -1900,6 +1901,7 @@ add_executable(oaisim
   ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
   ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
   ${OPENAIR_DIR}/common/utils/utils.c
+  ${OPENAIR_DIR}/common/utils/system.c
   ${GTPU_need_ITTI}
   ${OPENAIR_TARGETS}/COMMON/create_tasks.c
   ${HW_SOURCE}
diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt
index 61d1565bac912d2e03eb6c183a3d0f479ce161f2..db49a9181d6009523a8e596b18d54add9603da16 100755
--- a/cmake_targets/at_commands/CMakeLists.txt
+++ b/cmake_targets/at_commands/CMakeLists.txt
@@ -716,6 +716,7 @@ ADD_EXECUTABLE(at_nas_ue  ${OPENAIR_NAS_DIR}/UE/UEprocess.c
                           ${OPENAIR_NAS_DIR}/UE/nas_proc.c  
                           ${OPENAIR_NAS_DIR}/UE/nas_user.c  
                           ${OPENAIR_DIR}/common/utils/utils.c
+                          ${OPENAIR_DIR}/common/utils/system.c
                           )
                           
 target_link_libraries (at_nas_ue 
diff --git a/common/utils/system.c b/common/utils/system.c
new file mode 100644
index 0000000000000000000000000000000000000000..52fb950e37f2179c9c4de895c1ab9dd456f93230
--- /dev/null
+++ b/common/utils/system.c
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/* This module provides a separate process to run system().
+ * The communication between this process and the main processing
+ * is done through unix pipes.
+ *
+ * Motivation: the UE sets its IP address using system() and
+ * that disrupts realtime processing in some cases. Having a
+ * separate process solves this problem.
+ */
+
+#include "system.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+
+#define MAX_COMMAND 4096
+
+static int command_pipe_read;
+static int command_pipe_write;
+static int result_pipe_read;
+static int result_pipe_write;
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int module_initialized = 0;
+
+/********************************************************************/
+/* util functions                                                   */
+/********************************************************************/
+
+static void lock_system(void)
+{
+  if (pthread_mutex_lock(&lock) != 0) {
+    printf("pthread_mutex_lock fails\n");
+    abort();
+  }
+}
+
+static void unlock_system(void)
+{
+  if (pthread_mutex_unlock(&lock) != 0) {
+    printf("pthread_mutex_unlock fails\n");
+    abort();
+  }
+}
+
+static void write_pipe(int p, char *b, int size)
+{
+  while (size) {
+    int ret = write(p, b, size);
+    if (ret <= 0) exit(0);
+    b += ret;
+    size -= ret;
+  }
+}
+
+static void read_pipe(int p, char *b, int size)
+{
+  while (size) {
+    int ret = read(p, b, size);
+    if (ret <= 0) exit(0);
+    b += ret;
+    size -= ret;
+  }
+}
+
+/********************************************************************/
+/* background process                                               */
+/********************************************************************/
+
+/* This function is run by background process. It waits for a command,
+ * runs it, and reports status back. It exits (in normal situations)
+ * when the main process exits, because then a "read" on the pipe
+ * will return 0, in which case "read_pipe" exits.
+ */
+static void background_system_process(void)
+{
+  int len;
+  int ret;
+  char command[MAX_COMMAND+1];
+
+  while (1) {
+    read_pipe(command_pipe_read, (char*)&len, sizeof(int));
+    read_pipe(command_pipe_read, command, len);
+    ret = system(command);
+    write_pipe(result_pipe_write, (char *)&ret, sizeof(int));
+  }
+}
+
+/********************************************************************/
+/* background_system()                                              */
+/*     return -1 on error, 0 on success                             */
+/********************************************************************/
+
+int background_system(char *command)
+{
+  int res;
+  int len;
+
+  if (module_initialized == 0) {
+    printf("FATAL: calling 'background_system' but 'start_background_system' was not called\n");
+    abort();
+  }
+
+  len = strlen(command)+1;
+  if (len > MAX_COMMAND) {
+    printf("FATAL: command too long. Increase MAX_COMMAND (%d).\n", MAX_COMMAND);
+    printf("command was: '%s'\n", command);
+    abort();
+  }
+  /* only one command can run at a time, so let's lock/unlock */
+  lock_system();
+  write_pipe(command_pipe_write, (char*)&len, sizeof(int));
+  write_pipe(command_pipe_write, command, len);
+  read_pipe(result_pipe_read, (char*)&res, sizeof(int));
+  unlock_system();
+  if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) return -1;
+  return 0;
+}
+
+/********************************************************************/
+/* start_background_system()                                        */
+/*     initializes the "background system" module                   */
+/*     to be called very early by the main processing               */
+/********************************************************************/
+
+void start_background_system(void)
+{
+  int p[2];
+  pid_t son;
+
+  module_initialized = 1;
+
+  if (pipe(p) == -1) {
+    perror("pipe");
+    exit(1);
+  }
+  command_pipe_read  = p[0];
+  command_pipe_write = p[1];
+
+  if (pipe(p) == -1) {
+    perror("pipe");
+    exit(1);
+  }
+  result_pipe_read  = p[0];
+  result_pipe_write = p[1];
+
+  son = fork();
+  if (son == -1) {
+    perror("fork");
+    exit(1);
+  }
+
+  if (son) {
+    close(result_pipe_write);
+    close(command_pipe_read);
+    return;
+  }
+
+  close(result_pipe_read);
+  close(command_pipe_write);
+
+  background_system_process();
+}
diff --git a/common/utils/system.h b/common/utils/system.h
new file mode 100644
index 0000000000000000000000000000000000000000..784c15fc9a045d6b83e5136fe00122a65c7789b6
--- /dev/null
+++ b/common/utils/system.h
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _SYSTEM_H_OAI_
+#define _SYSTEM_H_OAI_
+
+/****************************************************
+ * send a command to the background process
+ *     return -1 on error, 0 on success
+ ****************************************************/
+
+int background_system(char *command);
+
+/****************************************************
+ * initialize the background process
+ *     to be called very early
+ ****************************************************/
+
+void start_background_system(void);
+
+#endif /* _SYSTEM_H_OAI_ */
diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c
index bfa4a04cc82dd9d73946ac67702897fe2dce8a51..4700187da179a45ffef1388623a12539881b8673 100644
--- a/openair3/NAS/UE/ESM/esm_ebr_context.c
+++ b/openair3/NAS/UE/ESM/esm_ebr_context.c
@@ -47,6 +47,7 @@ Description Defines functions used to handle EPS bearer contexts.
 #include "esm_ebr_context.h"
 
 #include "emm_sap.h"
+#include "system.h"
 
 #if defined(ENABLE_ITTI)
 # include "assertions.h"
@@ -286,7 +287,18 @@ int esm_ebr_context_create(
              LOG_TRACE(INFO, "ESM-PROC  - executing %s ",
                        command_line);
 
-             if (system(command_line)) ; /* TODO: what to do? */
+             /* Calling system() here disrupts UE's realtime processing in some cases.
+              * This may be because of the call to fork(), which, for some
+              * unidentified reason, interacts badly with other (realtime) threads.
+              * background_system() is a replacement mechanism relying on a
+              * background process that does the system() and reports result to
+              * the parent process (lte-softmodem, oaisim, ...). The background
+              * process is created very early in the life of the parent process.
+              * The processes interact through standard pipes. See
+              * common/utils/system.c for details.
+              */
+             if (background_system(command_line) != 0)
+               LOG_TRACE(ERROR, "ESM-PROC - failed command '%s'", command_line);
 
              break;
 
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 03f6ba1a2eddfbc02ca337d6572457e3ecd10f60..ee31831a6b3b35d4d24ad065bc42f064ff7f3f10 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -74,6 +74,8 @@ unsigned short config_frames[4] = {2,9,11,13};
 #include "create_tasks.h"
 #endif
 
+#include "system.h"
+
 #ifdef XFORMS
 #include "PHY/TOOLS/lte_phy_scope.h"
 #include "stats.h"
@@ -1371,6 +1373,8 @@ int main( int argc, char **argv ) {
     int ret;
 #endif
 
+    start_background_system();
+
 #ifdef DEBUG_CONSOLE
     setvbuf(stdout, NULL, _IONBF, 0);
     setvbuf(stderr, NULL, _IONBF, 0);
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index f1b3944a164609631d38ad1c6312289f478b1bfd..ab801d685c60bf001f402bcc1842d026b3a19f87 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -59,6 +59,7 @@
 
 #include "SCHED/defs.h"
 #include "SCHED/vars.h"
+#include "system.h"
 
 
 #include "PHY/TOOLS/lte_phy_scope.h"
@@ -1194,6 +1195,8 @@ main (int argc, char **argv)
 
   clock_t t;
 
+  start_background_system();
+
 #ifdef SMBV
   // Rohde&Schwarz SMBV100A vector signal generator
   strcpy(smbv_ip,DEFAULT_SMBV_IP);