DeviceProxy may failed to reconnect on Windows

Hi tangoer:

On Windows test (Windows11 + VS2019 + libtango_10.3.0_v143_x64_shared_release.zip from GitLab cppTango release), i find that DeviceProxy may failed to reconnect after server restart.

The C++ test code:

#include <tango/tango.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <random>

#define COPY_DEVICEPROXY  // copy DeviceProxy to access device's command or attribute.


int main(int argc,char *argv[]) {
  Tango::DeviceProxy dev("sys/tg_test/1");  // TangoTest server
  std::cout << "press Ctrl+C to exit ...\n";

#ifdef COPY_DEVICEPROXY
  Tango::DeviceProxy dev_copy = dev;
  // DeviceProxy have copy ctor and copy assignment operator,
  // but no move ctor and move assignment operator.
#endif

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<> dis(500, 15000);  // 0.5s - 15s random delay.

  while(true) {
    try {
      std::this_thread::sleep_for(std::chrono::milliseconds(dis(gen)));
      // std::this_thread::sleep_for(std::chrono::milliseconds(10000));
      // if sleep >= 10s, the probability of CORBA::TRANSIENT exception will increase?
      dev.command_inout("state");
      std::cout << "Execute 'state' command OK.\n";
    }
    catch(const CORBA::TRANSIENT& ex) {
      std::cout << "Exception: " << ex._name()
                << ", minor: " << ex.minor() << ".\n";
    }
    catch (const Tango::DevFailed &ex) {
      // Tango::Except::print_exception(ex);
      std::cout << "Exception: " << ex.errors[0].desc.in() << ".\n";
    }
    catch (...)	{
      std::cout << "Unkown exception.\n";
    }

#ifdef COPY_DEVICEPROXY
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    try {
      dev_copy.command_inout("status");
      std::cout << "Execute 'status' command OK -- DeviceProxy copy.\n";
    }
    catch(const CORBA::TRANSIENT& ex) {
      std::cout << "Exception: " << ex._name()
                << ", minor: " << ex.minor() << " -- DeviceProxy copy.\n";
    }
    catch (const Tango::DevFailed &ex) {
      std::cout << "Exception: " << ex.errors[0].desc.in() << " -- DeviceProxy copy.\n";
    }
    catch (...)	{
      std::cout << "Unkown exception -- DeviceProxy copy.\n";
    }
#endif
  } // while(true)

  return EXIT_SUCCESS;
}

Start the TangoTest server, the above test output (I add some comments about stop and start TangoTest server):

press Ctrl+C to exit ...
Execute 'state' command OK.
Execute 'status' command OK -- DeviceProxy copy.
Execute 'state' command OK.
Execute 'status' command OK -- DeviceProxy copy.
Execute 'state' command OK.
Execute 'status' command OK -- DeviceProxy copy.
# Ctrl+C to stop TangoTest server
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
# start TangoTest server
Execute 'state' command OK.
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Execute 'state' command OK.
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
# Ctrl+C to stop TangoTest server
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Exception: Device sys/tg_test/1 is not exported (hint: try starting the device server).
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
# start TangoTest server
Execute 'state' command OK.
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Execute 'state' command OK.
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.
Execute 'state' command OK.
Exception: TRANSIENT, minor: 1096024072 -- DeviceProxy copy.

When occured CORBA::TRANSIENT exception (i can’t get why this exception), the DeviceProxy will never reconnected successfully again (like dev_copy in above C++ code).

Even without define COPY_DEVICEPROXY macro (only operate on dev in above C++ code), there is a certain probability for CORBA::TRANSIENT exception occurring, it’s just not easy to reproduce this issue. Once CORBA::TRANSIENT exception occurs, it is impossible to reconnect successfully again.

Anyone can reproduce this issue on Windows?

I don’t think copying a DeviceProxy is a particular good idea, but it’s our job to fix that, see DeviceProxy copy/assignment operators look odd (#1638) · Issues · tango-controls / cppTango · GitLab.

But if you don’t copy it, it should work. Can you reproduce the issue on Linux?

I can not reproduce this issue on Linux (don’t copy DeviceProxy), it looks like only on Windows.

Thanks for checking, I’ve created Investigate DeviceProxy copy ctor bug (Windows) (#1656) · Issues · tango-controls / cppTango · GitLab to track this.