They should be disconnected automatically.
What is probably happening in your case is that the signal is firing before the Node is finished being freed.
queue_free() is deferred and usually happens a frame later or at least after everything has processed in the current frame.
This allows it to safely finish some things, but if you have a signal firing before the Node is gone, you'll have some timing issues.
I've had a lot of timing issues with the core Node events, notifications, and signals. There are usually ways to account for them with extra care, but they're not immediately obvious, and can take a lot of debugging.
That said, I've found that code to be too difficult to maintain in practice, and generally use the entry and exit points of Godot in very few things. I've resorted to my own methods for initialization and cleaning up nodes. When doing this I can quickly review when and what exactly happens.
queue_free() I would have the game invoke a custom clean up method to have more control. For an enemy it would play all its death effects, then hide itself and do all the immediate work needed to get the Node in the right state. It may even involve delays or timers. Lastly, it would kick off something like
queue_free() when it is truly being disregarded.
In many cases its nothing more than
queue_free(), but I have at least the option to go back and expand that when issues like these get introduced if changes are made later.
You may also still have to be dealing with disconnecting a lot of signals. If this is the case, and you have a common set of signals you can usually loop through lists and disconnect things using the information found in
get_signal_connection_list(). It's generally a lot less code, and in many cases very re-usable.