[Gambas-user] can't terminate fluidsynth processes by sending "quit" command over socket

Doriano Blengino doriano.blengino at ...1909...
Thu May 7 07:42:53 CEST 2009


Kevin Fishburne ha scritto:
> Hello everyone. I'm having an odd issue that's got me stumped. My GAMBAS
> app opens several fluidsynth daemons listening on different ports and
> communicates with them over a socket. While they do all send and receive
> commands properly, when I issue the "quit" command to any of the
> fluidsynth daemons they don't actually terminate. They do respond with
> "Cheers!", which is what they say when they terminate, but the processes
> remain and they continue responding to commands. I have to use SHELL
> "pkill fluidsynth", which leaves the daemons unable to be restarted
> because they can't bind to their designated port/socket afterward for
> some reason.
>
> At first I thought it was fluidsynth behaving badly, but I'm able to
> telnet to the fluidsynth daemon and issue the "quit" command
> successfully using the same shell command as GAMBAS. I'm starting
> fluidsynth with the following command:
>
> SHELL "fluidsynth --connect-jack-outputs --no-shell --verbose --server
> --audio-driver=jack --midi-channels=1 --portname=LiquidSynth01
> -oshell.port=9800 -oaudio.jack.id=LiquidSynth01 -omidi.driver=alsa_seq
> -omidi.portname=LiquidSynth01 -omidi.alsa_seq.id=LiquidSynth01"
>
> My code to stop the fluidsynth daemons is:
>
> DIM i AS Integer
>
> ' Stop FluidSynth.
> FOR i = 1 TO 16
>   Send_To_FluidSynth("quit", i)
>   SLEEP 0.125
> NEXT
>
> PUBLIC SUB Send_To_FluidSynth(FluidString AS String, Daemon AS Integer)
>
>   ' Send a command to FluidSynth
>   DIM Timeout AS Single
>   FluidString = FluidString & "\n" ' Add carriage return to command is
> executed.
>   Socket = NEW Socket
>   Socket.Connect("localhost", 9799 + Daemon)
>   DO WHILE (Socket.Status <> 7) AND (Socket.Status > 0)
>     WAIT 0.1
>     Timeout = Timeout + 0.1
>     IF Timeout >= 0.25 THEN EXIT 
>   LOOP
>   Timeout = 0
>   IF Socket.Status = 7 THEN 
>     ' Socket is good, send command.
>     WRITE #Socket, FluidString, Len(FluidString)
>     PRINT "Sending command to FluidSynth daemon: " & FluidString
>   END IF
>   DO WHILE Lof(Socket) = 0
>     WAIT 0.1
>     Timeout = Timeout + 0.1
>     IF Timeout >= 0.25 THEN EXIT
>   LOOP 
>   READ #Socket, FluidString, Lof(Socket)
>   PRINT "FluidSynth daemon replies with: " & FluidString
>   CLOSE #Socket
>
> END
>
> As you can see there are 16 fluidsynth daemons starting at port 9800 and
> going up to port 9815. The for/next loop just cycles through these 16
> ports to terminate each process sequentially. I added the timeout stuff
> because if the code runs with no fluidsynth processes active/listening
> it just hangs there in the do/loop loops.
>
> Here's my debug/console output right after trying to quit the fluidsynth
> daemons, including anything they replied with:
>
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Sending command to FluidSynth daemon: quit
> FluidSynth daemon replies with: cheers!
> Terminated
> WARNING: Child process terminated by signal 15
> cannot read server event (Success)
> cannot complete execution of the processing graph (Resource temporarily
> unavailable)
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> cannot complete execution of the processing graph (Success)
> cannot complete execution of the processing graph (Success)
> zombified - calling shutdown handler
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> zombified - calling shutdown handler
> fluidsynth: error: Help! Lost the connection to the JACK server
> Failure to resume: Invalid argument
>
> The messages about JACK are because JACK is terminated after I attempt
> to terminate the fluidsynth daemons. Of course if they actually
> terminated properly they'd have nothing to complain about. I have no
> idea what's up with the "zombified" messages. Any ideas anyone?
>   
I don't know fluidsynth enough, and I never used sockets with gambas, 
but some idea could be stated anyway.
A "zombie" is a process which has no more its parent. Every process in 
Linux is started by some other process, which then becomes the parent of 
the new process (the child). The parent should wait for the child to 
terminate, but if the parent terminates prematurely, then the child 
process becomes a zombie. What here seems to happen is that your program 
terminates before fluidsynth, turning it in a zombie. It seems that 
fluidsynth, noticing to be "zombified", chooses to terminate.

Perhaps the reason is somehow related to the way you communicate with it 
- just to start, I can say that a telnet program does many more things 
than a simple TCP connection, so you should investigate about this. Is 
fluidsynth able to communicate smoothly using a simple TCP connection, 
or it requires some more handshake?

A try you can do is to modify slightly your code for waiting a reply 
from the daemon:

  DO WHILE Lof(Socket) = 0
    WAIT 0.1
    Timeout = Timeout + 0.1
    IF Timeout >= 0.25 THEN EXIT
  LOOP 
  READ #Socket, FluidString, Lof(Socket)
  PRINT "FluidSynth daemon replies with: " & FluidString
  CLOSE #Socket


Here, you wait until something appears on the socket, then read it and 
close the socket; but it could be too soon. I think it would be better 
to wait for the EOF. May be that fluidsynth sends "cheers!" then, after 
a short time, it wants to send more. But your socket is already closed,

You could put a delay just after asking all daemons to stop; few 
milliseconds are not a long time, but a gambas program can do a lot of 
things in the meantime (ie, terminate too early...).

Does all the rest of the communication work properly? If yes, then 
probably you are near to success. If not, then it is a communication 
problem. Could be (I repeat, "could be") that you must send CR instead 
of newline, or something similar.

Hope this help, cheers! (but I am not terminating... :-))

-- 
Doriano Blengino

"Listen twice before you speak.
This is why we have two ears, but only one mouth."





More information about the User mailing list