Can someone break this [thread] code?

local sig = Instance.new("BindableEvent")

coroutine.wrap(function()
	while true do
		print("A:",sig.Event:Wait())
	end
end)()

sig.Event:Connect(function(...)
	print("B",...)
end)

Make the output of the loop differ from the connection (the A/B difference doesn’t count though xd)

E.g: thinkthings to try:

for i = 1,10 do
	sig:Fire(i)
end
3 Likes

Wrap the object being passed with a metatable and set its __tostring metamethod to include a debounce, and if it’s set return a different string.

EDIT: Nvm forgot tables are cloned through the Bindable.

1 Like

Probably more accurate to say w/ 100% deterministic results (no math.random etc) to make these separate scripts output different things:

local sig = Instance.new("BindableEvent")

coroutine.wrap(function()
	while true do
		print(sig.Event:Wait())
	end
end)()
local sig = Instance.new("BindableEvent")

sig.Event:Connect(function(...)
	print(...)
end)
sig.Event:Connect(function(object)
	object.Name = "B"
end)

---

local fireObj = Instance.new("Folder")
for i = 1, 10 do
	fireObj.Name = "A"
	sig:Fire(fireObj)
end

After the first fire, the connected function will run after A but before B, because connections are ran in the opposite order of when they’re added. In other words, it looks like this:

Connections:
* new connect
* sig B connect
* sig A wait

sig is fired

Connections:
* new connect
* sig B connect

sig A wait is called again

Connections:
* sig A wait
* new connect
* sig B connect

sig is fired and the following lines are then repeated for the next 9 iterations.

B B
A: B
A: A
B B
A: A
B B
A: A
B B
...

This is the only way to do this that I can think of. Metatables – as well as some other things – are lost when transferring tables over Bindables. In fact, you don’t even receive the same table, you receive a copy. This means that __tostring tricks won’t work. I think that Instance is the only mutable types that lets you change its tostring representation.

I don’t know if this fits your “with 100% deterministic results” criteria. This will have a different result for only the first fire. After that, it will always give different results between the two listeners. This is deterministic, so it technically fits what you’re asking for.

It’s worth noting that on the first fire of the event, your B may print before A depending on whether the Wait script (A) or the Connect script (B) ran first. Which one is first for the first fire is deterministic only if both are ran in a deterministic way. If they’re ran in a non-deterministic way e.g. as separate scripts, then whether A or B will be first for the first fire is pretty much random.Technically, them being separate scripts is probably deterministic, but it will depend on which script was created first, which is pretty much random and not at all a reasonable thing to rely on.

Also, while the behavior I’m exploiting here is consistent at the moment, I don’t think there are any guarantees that this behavior won’t change.


Oh, with the it-makes-copies-of-tables stuff being said, it’s worth noting that the following works but isn’t deterministic:

for i = 1, 10 do
	sig:Fire({})
end
B table: 453E9174
A: table: 453E91A4
A: table: 453E9384
B table: 453E93E4
A: table: 453E98F4
B table: 453E9564
A: table: 453E9A14
B table: 453E9594
...

Since it makes a copy of the table for every listener, A and B are receiving different tables.

3 Likes

I should probably mention that ‘Instance.new(“BindableEvent”)’ would be replaced by my own signal constructor which has no table cloning. (Although memory address things would still vary)

Also by separate scripts I meant that there are two separate bindables and the scripts are running at separate times

I don’t really mean to break it by mutating external objects, what I’m looking for is a way to show that the loop may return different results than the connect

AFAIK these should be the same. Under the hood :Wait() should be using the same mechanism to listen to the event and could be just as simple as doing a :Connect() :Disconnect() equivalent behind the scenes. You would need someone with knowledge of the implementation details for further info.

2 Likes