After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 611941 - Copied signals display unexpected behavior
Copied signals display unexpected behavior
Status: RESOLVED NOTABUG
Product: libsigc++
Classification: Bindings
Component: signals
unspecified
Other Linux
: Normal normal
: ---
Assigned To: libsigc++ maintainer(s)
libsigc++ maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2010-03-05 20:25 UTC by Jonathon Jongsma
Modified: 2014-07-29 08:18 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Jonathon Jongsma 2010-03-05 20:25:23 UTC
In essence, if you copy a sigc::signal, all of the slots that were registered on any of the copies will be triggered whenever that signal is emitted (from any of the copies).  Potential solution is to simply disable copying of sigc::signals.  See this mailing list thread for more information: http://mail.gnome.org/archives/gtkmm-list/2010-March/msg00013.html
Comment 1 Krzysztof Kosiński 2010-07-26 22:48:26 UTC
In Boost.Signals2, signals are not copyable.
Comment 2 Kjell Ahlstedt 2011-04-27 08:14:44 UTC
This surprising behaviour is documented, although quite tersely at
http://developer.gnome.org/libsigc++/stable/group__signal.html:

"When signals are copied they share the underlying information, so you can have
a protected/private sigc::signal member and a public accessor method."

I suppose this means that you can have a method like
  MySignal MyClass::get_my_signal();
and use the returned copy of the signal for connecting and disconnecting slots.
But it's a strange motivation for the copy behaviour. An accessor that can be
used for modifying the accessed object should return a reference or a pointer
rather than a copy, shouldn't it?
Comment 3 Murray Cumming 2011-07-19 09:43:46 UTC
I guess that this implicit sharing was done to avoid orphaned references or pointers.
Comment 4 André Klapper 2011-09-22 09:02:13 UTC
[Resetting QA Contact and Assignee to default - see bug 659799 for more info]
Comment 5 Kjell Ahlstedt 2014-07-28 08:29:20 UTC
sigc::signal is a reference-counting pointer in disguise. I've documented
this fact more clearly. It's not a bug, it's a feature. At least it's by
design.
https://git.gnome.org/browse/libsigc++2/commit/?id=1b05b5a573d737e3c29056d449ebc299c26d22e3

In the gtkmm-list thread referred to in comment 0, several people have
recommended that signals shall be non-copyable. That's probably easy to
implement, but of course it would break API. It's not likely to occur soon.

What about deprecating the copy constructor and the assignment operator?
I can test if that would affect libsigc++, glibmm or gtkmm in any serious way.
Comment 6 Murray Cumming 2014-07-28 08:38:15 UTC
Maybe if you try to make signal non-copyable then you'll find out a reason for it to be copyable. For instance, maybe it's needed to bind one signal to another. Or maybe it's not useful at all. Hopefully the tests exercise it if it's useful.
Comment 7 Kjell Ahlstedt 2014-07-28 14:04:15 UTC
I made sigc::signal_base non-copyable and built (make && make install &&
make check) libsigc++2, glibmm, gtkmm, atkmm, goocanvasmm, pangomm and
gtkmm-documentation.

The only place where a signal is copied is in gtkmm-documentation/examples/
book/signals/custom. That example can easily be rewritten.

These tests indicate that copied signals are rarely used. Still, I'm not sure
it's a good idea to deprecate signal_base's copy constructor and assignment
operator. Wouldn't users that feel they need a copy, be tempted to make a
function that returns a pointer or a reference to the signal? That opens up
the possibility for dangling pointers and references.
The only problem I see with copyable signals is that it's not obvious that a
sigc::signal is primarily a pointer to a reference counted signal_impl. A copy
of a sigc::signal is comparable with a copy of a Glib::RefPtr<SomeClass>.
Comment 8 Murray Cumming 2014-07-29 07:43:07 UTC
Wouldn't preventing signal copying break the common (mine too) practice of using an accessor function to get the signal. For instance, here:
https://git.gnome.org/browse/glom/tree/glom/utility_widgets/notebook_noframe.h#n54

or:

class Thing
{
public:
  sigc::signal<void, int> signal_something();

private:
  sigc::signal<void, int> m_signal_something;
}



We use the same technique in glibmm/gtkmm, though it's a proxy object, rather than a sigc::signal itself, that we return.
Comment 9 Kjell Ahlstedt 2014-07-29 08:18:09 UTC
(In reply to comment #8)
> Wouldn't preventing signal copying break the common (mine too) practice of
> using an accessor function to get the signal.

Yes, it would. The accessor function would have to return a pointer or a
reference (sigc::signal<void,int>* or sigc::signal<void,int>&), and that's more
error-prone. Can result in dangling pointers or dangling references.

It looks like we can agree that sigc::signal shall remain copyable.
The documentation I've added (see comment 5) hopefully makes it less likely
that people misunderstand the meaning of the copy operation.