I figured out why fproxy.enabled sometimes resets itself to "false" desptir
it's never set explicitly to this value.
This effect appears when the node is shut down right after startup, e.g. by a
BindException and has been reported by people several times.
It is somewhat complicated to explain, evenmore as English isn't my native
language but I'll try my best :)
Problem Summary:
- the critical line is in "SimpleToadletServer", class "FproxyEnabledCallback()"
- it's get() method returns true or false depending on "myThread" being null or
not
Situation: Node starts, does this and that and finally creates a
SimpleToadletServer object. We're now tracing from the constructor:
- config stuff (later more to these)
- setting the local "enabled" variable depending on "fproxy.enabled="
- "myThread" is initially null and stays so if "!enabled" because it doesn't
get set to something else. The if is around line 155 ("around" because I have
modified several files with debug output to trace this one down, but you'll
find what I mean)
- but if "enabled", the whole FProxy thing is launched around line 159 by the
"else" case
- after that the NetworkInterface created
- after that "myThread" is set to a newly created Thread object
The observable effect is, if the NetworkInterface fails because of e.g. a
BindException, "myThread" is still null because it is set to something AFTER
the NetworkInterface has initialized.
So when we assume the node exists because of the BindException:
- the FilePersistentConfig gets activated to write the configuration to
freenet.ini
- it grabs all configuration settings in FilePersistentConfig.exportFieldSet()
which itself calls for all SubConfigs SubConfig.exportFieldSet()
- SubConfig.exportFieldSet() calls Option.getValueString()
- the Option object for "fproxy.enabled=" is of course a BooleanOption object
as it's a boolean config option
- BooleanOption.getValueString() depends on something called
config.hasFinishedInitialization()
- if that methods returns true, which it does in this case, cb.get() is called
- cb however is an object of BooleanCallback
- in SimpleToadletServer, the method FproxyEnabledCallback() is passed around
line 132 as a parameter for "fproxyConfig.register("enabled",...,new
FproxyEnabledCallback())"
- so cb.get() calls FproxyEnabledCallback().get()
- as already said, FproxyEnabledCallback().get() returns true or false
depending on "myThread" being null or not
- but because mythread IS STILL NULL becuase it is set to the new Thread()
AFTER the NetworkInterface() init happened
- therefore the callback returns "false", which gets written into the config
file.
I'm not sure if the "new NetworkInterface()" line can be moved down to after
where the thread has been created, therefore I let you (toad) decide how to
resolve this problem without creating race conditions or other weird stuff.
HTH