Is it safe to use tcp_write(), tcp_output(), etc from task
#2 in this scenario?
Thats one possibility, but blocking the network task is not enough: you also would have to ensure that you haven't interrupted it while it's inside the lwIP code somewhere.
Do I need to put the tcp_write() call in
a critical section that blocks the network task from running?
And that's the 2nd possibility, which is implemented by our API layer, BTW (e.g. by calling tcpip_callback).
would it be safer/better to have queues going both ways to where the network
task main loop checks for pending calls to tcp_write()?
Both possibilities work fine, it's up to you which one you like best.