Skip to content

Subscritptions are run twice #2236

Description

@snaggen

Is there an existing issue for this?

  • I have searched the existing issues.

Is this issue related to iced?

  • My hardware is compatible and my graphics drivers are up-to-date.

What happened?

I started to notice that the Subscription::channel closure in Cosmic Term run twice on startup, and started to track it backwards in the stack. This only happens with --release builds, and not an all platforms ( https://github.com/jackpot51 could not reproduce this on his hardware ), on my Thinkpad T15 Gen 1, it happens every time.

So, I notice that in iced/winit/src/application.rs we actually have two calls to runtime.track(application.subscription(...)). One in run_instance and another in update. Both these calls will trigger a new call to cosmic terms subscription::channel closure. This should not happen since there is a check in tracker.rs to prevent this:

if self.subscriptions.contains_key(&id) {

But for some reason, this check fails, the id between the first call is different from the calls in the update function. So, when I started to dig further I found that the hashing function for Map, is the one that is getting different from the first to the following calls, and more exact it is the self.mapper.hash(state); that differs.

self.mapper.hash(state);

And I debug print the self.mapper, the function pointers have different values. So, for some reason, it seems that the compiler, when run in release mode, decides to perform some optimizations to either move the closure between the calls, or create two different closures (I'm no expert in compiler optimizations, I just see that the closure have different pointers for the call from run_instance and update ).

This is a quite critical bug, since that causes Subscription::channel to be run twice, and if you don't count on that but assume it only run once, you may end up with a dead channel in the application.
In Cosmic Term, this was worked around by commit
pop-os/cosmic-term@4401a7d

The iced version is
https://github.com/pop-os/iced/tree/6115280d5277c50b8539d4eff6ab61050c51b592
since that is what libcosmic uses. But, I don't see anything that would have fixed this.

This is with rustc rustc 1.75.0 (82e1608df 2023-12-21)
some info from /proc/cpuinfo

model name  : Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtsc
p lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fm
a cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb
stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt x
saveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi md_clear flush_l1d arch_capabilities
vmx flags   : vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple pml ept_mode_base

What is the expected behavior?

The real fix would be to make the self.mapper.hash(state); stable.

Version

master

Operating System

Linux

Do you have any log output?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingshell

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions