title: Segmentation fault when communicating with USB device using ftdi
body: <p>I have a project requiring the use of Maxon EPOS under Linux. They provide libraries and code to integrate under Linux. Links are available below, 2 files libEposCmd.so and libftd2xx.so to copy into /etc/local/lib and /etc/lib and a Definition.h file.</p>
  
  <p>After following the procedure, compiling the file HelloEposCmd.cpp and trying the program to test communication with hardware via USB, the code gets a Segmentation fault.</p>
  
  <p>I have tried the same procedure on other machines, with Ubuntu 14.04 and 16.04 without trouble. So at this point I am not sure what is the problem, my machine, the code, issue with USB or something else.</p>
  
  <p>If that can help, my laptop is a MSI Gl62 and running on Ubuntu 16.04LTS 64 bits. I am not very familiar with Ubuntu.</p>
  
  <p>You can find the 2 library files, Definition.h file and the HelloEposCmd.cpp file.
  <a href="http://www.maxonmotor.com/medias/sys_master/root/8815100330014/EPOS-Linux-Library-En.zip" rel="nofollow noreferrer">http://www.maxonmotor.com/medias/sys_master/root/8815100330014/EPOS-Linux-Library-En.zip</a>
  And the installation guide: <a href="http://www.maxonmotor.com/medias/sys_master/root/8821690073118/EPOS-Command-Library-En.pdf" rel="nofollow noreferrer">http://www.maxonmotor.com/medias/sys_master/root/8821690073118/EPOS-Command-Library-En.pdf</a> at 9-Integration paragraph.</p>
  
  <p>Here is a sample of the code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include "Definitions.h"
  #include &lt;string.h&gt;
  #include &lt;sstream&gt;
  #include &lt;unistd.h&gt;
  #include &lt;getopt.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;list&gt;
  #include &lt;math.h&gt;
  
  typedef void* HANDLE;
  typedef int BOOL;
  
  using namespace std;
  
  void* g_pKeyHandle = 0;
  unsigned short g_usNodeId = 1;
  string g_deviceName;
  string g_protocolStackName;
  string g_interfaceName;
  string g_portName;
  int g_baudrate = 0;
  
  const string g_programName = "HelloEposCmd";
  
  #ifndef MMC_SUCCESS
  #define MMC_SUCCESS 0
  #endif
  
  #ifndef MMC_FAILED
  #define MMC_FAILED 1
  #endif
  
  #ifndef MMC_MAX_LOG_MSG_SIZE
  #define MMC_MAX_LOG_MSG_SIZE 512
  #endif
  
  void  LogError(string functionName, int p_lResult, unsigned int p_ulErrorCode);
  void  LogInfo(string message);
  void  PrintUsage();
  void  PrintHeader();
  void  PrintSettings();
  int   OpenDevice(unsigned int* p_pErrorCode);
  int   CloseDevice(unsigned int* p_pErrorCode);
  void  SetDefaultParameters();
  int   ParseArguments(int argc, char** argv);
  int   DemoProfilePositionMode(HANDLE p_DeviceHandle, unsigned short p_usNodeId, unsigned int &amp; p_rlErrorCode);
  int   Demo(unsigned int* p_pErrorCode);
  </code></pre>
  
  <p>The function where the Segfault appears:</p>
  
  <pre><code>int OpenDevice(unsigned int* p_pErrorCode)
  {
  int lResult = MMC_FAILED;
  
  char* pDeviceName = new char[255];
  char* pProtocolStackName = new char[255];
  char* pInterfaceName = new char[255];
  char* pPortName = new char[255];
  
  strcpy(pDeviceName, g_deviceName.c_str());
  strcpy(pProtocolStackName, g_protocolStackName.c_str());
  strcpy(pInterfaceName, g_interfaceName.c_str());
  strcpy(pPortName, g_portName.c_str());
  
  LogInfo("Open device...");
  
  g_pKeyHandle = VCS_OpenDevice(pDeviceName, pProtocolStackName, pInterfaceName, pPortName, p_pErrorCode);
  
  if(g_pKeyHandle!=0 &amp;&amp; *p_pErrorCode == 0)
  {
      unsigned int lBaudrate = 0;
      unsigned int lTimeout = 0;
  
      if(VCS_GetProtocolStackSettings(g_pKeyHandle, &amp;lBaudrate, &amp;lTimeout, p_pErrorCode)!=0)
      {
          if(VCS_SetProtocolStackSettings(g_pKeyHandle, g_baudrate, lTimeout, p_pErrorCode)!=0)
          {
              if(VCS_GetProtocolStackSettings(g_pKeyHandle, &amp;lBaudrate, &amp;lTimeout, p_pErrorCode)!=0)
              {
                  if(g_baudrate==(int)lBaudrate)
                  {
                      lResult = MMC_SUCCESS;
                  }
              }
          }
      }
  }
  else
  {
      g_pKeyHandle = 0;
  }
  
  delete []pDeviceName;
  delete []pProtocolStackName;
  delete []pInterfaceName;
  delete []pPortName;
  
  return lResult;
  }
  </code></pre>
  
  <p>The main:</p>
  
  <pre><code>int main(int argc, char** argv)
  {
  int lResult = MMC_FAILED;
  unsigned int ulErrorCode = 0;
  
  PrintHeader();
  
  SetDefaultParameters();
  
  if((lResult = ParseArguments(argc, argv))!=MMC_SUCCESS)
  {
      return lResult;
  }
  
  PrintSettings();
  
  if((lResult = OpenDevice(&amp;ulErrorCode))!=MMC_SUCCESS)
  {
      LogError("OpenDevice", lResult, ulErrorCode);
      return lResult;
  }
  
  if((lResult = PrepareDemo(&amp;ulErrorCode))!=MMC_SUCCESS)
  {
      LogError("PrepareDemo", lResult, ulErrorCode);
      return lResult;
  }
  
  if((lResult = Demo(&amp;ulErrorCode))!=MMC_SUCCESS)
  {
      LogError("Demo", lResult, ulErrorCode);
      return lResult;
  }
  
  if((lResult = CloseDevice(&amp;ulErrorCode))!=MMC_SUCCESS)
  {
      LogError("CloseDevice", lResult, ulErrorCode);
      return lResult;
  }
  
  return lResult;
  }
  </code></pre>
  
  <p>The result from gdb backtrace:</p>
  
  <pre><code>~/EPOS_Linux_Library/example/src$ gdb HelloEposCmd coreGNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
  Copyright (C) 2016 Free Software Foundation, Inc.
  License GPLv3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html&gt;
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  and "show warranty" for details.
  This GDB was configured as "x86_64-linux-gnu".
  Type "show configuration" for configuration details.
  For bug reporting instructions, please see:
  &lt;http://www.gnu.org/software/gdb/bugs/&gt;.
  Find the GDB manual and other documentation resources online at:
  &lt;http://www.gnu.org/software/gdb/documentation/&gt;.
  For help, type "help".
  Type "apropos word" to search for commands related to "word"...
  Reading symbols from HelloEposCmd...(no debugging symbols found)...done.
  [New LWP 2436]
  [New LWP 2437]
  [New LWP 2439]
  [New LWP 2440]
  [Thread debugging using libthread_db enabled]
  Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
  Core was generated by `./HelloEposCmd'.
  Program terminated with signal SIGSEGV, Segmentation fault.
  #0  0x00007fc3eca0a960 in _xend ()
  at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:33
  33  ../sysdeps/unix/sysv/linux/x86/elision-unlock.c: No such file or directory.
  [Current thread is 1 (Thread 0x7fc3edcbc740 (LWP 2436))]
  
  
  (gdb) backtrace
  #0  0x00007fc3eca0a960 in _xend ()
  at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:33
   #1  __lll_unlock_elision (lock=0x10a1138, private=0)
  at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:29
  #2  0x00007fc3ec7e2934 in EventDestroy () from /usr/local/lib/libftd2xx.so
  #3  0x00007fc3ec7db2e8 in FT_Close () from /usr/local/lib/libftd2xx.so
  #4  0x00007fc3ec7e166b in FT_CreateDeviceInfoList ()
   from /usr/local/lib/libftd2xx.so
  #5  0x00007fc3ed82c911 in CMmcFtd2xxHndlBase::CreateDeviceInfoList(unsigned int*) () from /usr/local/lib/libEposCmd.so
  #6  0x00007fc3ed82ca88 in CMmcFtd2xxHndlBase::GetDeviceInfos(std::list&lt;CUsbDeviceInfo*, std::allocator&lt;CUsbDeviceInfo*&gt; &gt;&amp;, unsigned short, unsigned short) ()
  from /usr/local/lib/libEposCmd.so
  #7  0x00007fc3ed7e2346 in CGatewayUSBToFtd2xxDrv::GetDeviceInfos(std::list&lt;CUsbDeviceInfo*, std::allocator&lt;CUsbDeviceInfo*&gt; &gt;&amp;) ()
  from /usr/local/lib/libEposCmd.so
  #8  0x00007fc3ed7e2b48 in CGatewayUSBToFtd2xxDrv::InitPortList() ()
  from /usr/local/lib/libEposCmd.so
  #9  0x00007fc3ed7deed1 in CPort_USB::InitGateway(CStdStr&lt;char&gt;, CGatewayIToDrv*) () from /usr/local/lib/libEposCmd.so
  #10 0x00007fc3ed7df232 in CPort_USB::InitPort(CStdStr&lt;char&gt;, CGatewayIToDrv*, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
   #11 0x00007fc3ed7cb04f in CInterface_USB::InitPort(CStdStr&lt;char&gt;, CErrorInfo*)
  ---Type &lt;return&gt; to continue, or q &lt;return&gt; to quit---
  () from /usr/local/lib/libEposCmd.so
  #12 0x00007fc3ed7cb19e in CInterface_USB::InitInterface(CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #13 0x00007fc3ed7caada in CInterface_USB::InitInterface(CErrorInfo*) ()
   from /usr/local/lib/libEposCmd.so
  #14 0x00007fc3ed7a6a92 in CInterfaceManager::I_InitInterface(CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #15 0x00007fc3ed7923ec in CProtocolStackBase::InitProtocolStack(CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #16 0x00007fc3ed7646e9 in CProtocolStackManager::PS_InitProtocolStack(CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #17 0x00007fc3ed73ce84 in CDeviceBase::InitDevice(CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #18 0x00007fc3ed6d06de in CDeviceCommandSetManager::DCS_InitDevice(CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CErrorInfo*) ()
   from /usr/local/lib/libEposCmd.so
  #19 0x00007fc3ed6aebd6 in CVirtualDeviceBase::InitVirtualDevice(CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
  #20 0x00007fc3ed684deb in CVirtualCommandSet_Manager::VCS_InitVirtualDevice(CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CStdStr&lt;char&gt;, CErrorInfo*) ()
   from /usr/local/lib/libEposCmd.so
  #21 0x00007fc3ed66d112 in CCommunicationModel::CreateVirtualCommandSetManager()
   () from /usr/local/lib/libEposCmd.so
  ---Type &lt;return&gt; to continue, or q &lt;return&gt; to quit---
  #22 0x00007fc3ed67ca75 in VCS_OpenDevice () from /usr/local/lib/libEposCmd.so
   #23 0x000000000040206e in OpenDevice(unsigned int*) ()
   #24 0x0000000000403a6c in main ()
  </code></pre>
  
  <p>For USB communication, I modified the 99-ftdi.rules file provided:</p>
  
  <pre><code>SUBSYSTEM=="usb|usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a8b0", GROUP="dialout", MODE="666", SYMLINK+="ftd2xx%n"
  </code></pre>
  
  <p>and copied to "/etc/udev/rules.d/" (this works with other machines).</p>
  
  <p>Thanks for the help</p>
  
  <p>Update:
  Using the newest version of FTDI (1.3.6) did not help.</p>
  
  <p>Since it is specific to my machine, here are the specs, if that can help:
  -Dual boot Windows 10 - Ubuntu 16.04LTS 64bits
  - Intel Core i7-6700HQ CPU 2.60GHw
  - Nividia GTX950M</p>
  
  <p>I have read issues of elision-unlock with Intel cores and maybe also caused by the graphic card, though I don't fully understand the issues, and how this simple program is related to the graphic card, or even using multiple cores.</p>