Qemu-Monitor - Problem bei Nutzung über Socket

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Jetzt hab ich den "socat" mal so aufgerufen:

Code: Alles auswählen

strace -o socat.out socat - UNIX:<pfad> <<EOT
> system_powerdown
> EOT
Und hier die letzten Zeilen der "socat.out":

Code: Alles auswählen

getsockname(5, {sa_family=AF_UNIX}, [112->2]) = 0
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
select(6, [0 5], [1 5], [], NULL)       = 4 (in [0 5], out [1 5])
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
read(0, "system_powerdown\n", 8192)     = 17
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
write(5, "system_powerdown\n", 17)      = 17
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
read(5, "QEMU 3.0.0 monitor - type 'help'"..., 8192) = 326
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
write(1, "QEMU 3.0.0 monitor - type 'help'"..., 326) = 326
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
select(6, [0 5], [1 5], [], NULL)       = 4 (in [0 5], out [1 5])
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
read(0, "", 8192)                       = 0
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
read(5, "\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33["..., 8192) = 289
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
write(1, "\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33[D\33["..., 289) = 289
recvfrom(3, 0x7ffd249b1540, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
shutdown(5, SHUT_WR)                    = 0
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
select(6, [5], [1], [], {tv_sec=0, tv_usec=500000}) = 2 (in [5], out [1], left {tv_sec=0, tv_usec=499995})
recvfrom(3, 0x7ffd249b15b0, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
read(5, "", 8192)                       = 0
recvfrom(3, 0x7ffd249b1040, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
shutdown(5, SHUT_WR)                    = 0
ioctl(1, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0
shutdown(5, SHUT_RDWR)                  = 0
recvfrom(3, 0x7ffd249b1890, 519, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Die Ressource ist zur Zeit nicht verfügbar)
exit_group(0)                           = ?
+++ exited with 0 +++
Ich seh da ebenfalls einen "select" ...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na vor allem liest der da ne eine Menge, schreibt auch eine Menge, und dadurch verzoegert sich das ganze ggf. einfach ausreichend lange.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Insbesondere wird diese ``QEMU 3.0.0 monitor - type 'help'``-Meldung von QEMU gelesen. Vielleicht erwartet QEMU ja, dass diese Meldung rausgeschrieben werden kann bevor es irgendwelche Kommandos verarbeitet.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Mach leider auch keinen Unterschied ...

Scheint, als ob zwischen "sock.sendall" und "sock.close" eine kurze Wartezeit notwendig ist ...

Hab gerade ein "time.sleep(0.1) versucht ... reicht aus.

Verstehen tu ich es immer noch nicht ... aber da es geht ...
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@midan23: ich verstehe nicht, warum Du hier noch herumprobierst, die Lösung habe ich doch schon gestern gepostet: die while-Schleife mit recv. Das ist die einfachste und sauberste Möglichkeit. `select` braucht man nur, wenn nicht bestimmt ist, ob der Server oder der Client sendet, oder beide gleichzeitig. Bei Dir ist aber die Reihenfolge Client sendet -> Server antwortet klar.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sirius3: Als ”erstes” sendet doch aber der Server. Vielleicht reicht es ja tatsächlich aus das zu lesen. Was Deine Lösung wahrscheinlich abdeckt wenn dem Server egal ist ob man die Daten erst liest oder erst nach dem senden des Kommandos. Das strace sieht so aus als wenn es dem Server egal wäre.

Edit: Aber so lange man nicht weiss wie gross der Empfangspuffer ist und wie viel der Server am Anfang sendet, ist es natürlich sauberer und sicherer erst zu lesen und dann das Kommando zu schicken.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: ich habe select nicht ins Spiel gebracht weil es hier Reihenfolgen-Ungereimtheiten gab. Sondern weil mich das Verhalten von Linux hier interessiert: warum wird die Kommunikation augenscheinlich nicht korrket durchgefuehrt, wenn man "fire und forget" betreibt. Das man durch warten oder so lange lesen bis die gegenseite weggeht das Problem loesen kann war klar. Nicht klar ist mir immer noch, wie man sicherstellen kann, dass etwas zumindest den eigenen Prozess/Socket verlassen hat (Verhalten der Gegenstelle hat man ja nicht unter Kontrolle). Das select theoretisch eben schreibfaehigkeit signalisiert ist einfach nur ein Ansatz gewesen. Eigentlich ist das mE aber fuer volle Buffer gedacht die sonst das schreiben blockieren wuerded. Die bei einem solchen kurzen Statement nicht zu erwarten sind. Dein Ansatz hilft hier ja auch nicht, wenn von der Gegenstelle einfach nichts kommt. Kann sein, dass die Antwort ist "geht halt nicht".
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Ich denke, die Funktion wird erst mal so bleiben:

Code: Alles auswählen

def send(path):
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect(path)
    sock.sendall("system_powerdown\n")
    while True:
        if not sock.recv(100):
            break
    sock.close()
Wenn das "sock.sendall" nach der "while"-Schleife kommt, bleibt das Script stehen und die VM läuft weiter.
Ich vermute mal, wenn die VM gestoppt wird, wird auch das Script beendet, aber das habe ich nicht ausprobiert.

Interessant ist, das die Funktion erst verlassen wird, nachdem die VM gestoppt wurde ...
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@__blackjack__: korrekt wäre, erst bist zum Prompt "(qemu)" zu lesen, dann das Kommando zu schreiben und wieder bis zum Prompt lesen.
@__deets__: qemu scheint ein Kommando erst auszuführen, nachdem es die Eingabe zum Client zurückgeechot hat. Da aber, wenn der Client den Socket sofort schließt, es beim `send` auf dem Server zu einem Fehler kommt, wird das Kommando komplett abgebrochen, ich erwarte, das taucht auch irgendwo in den Server-Logs auf, da könnte man mal nachschauen. Wartet man dagegen, klappt das Senden und die Antwort landet beim Client im Input-Buffer (was ja bei Unix-Sockets identisch ist mit dem Output-Buffer des Servers) und der ist mit 212992 Bytes groß genug, um den gesamten Output (vor und nach dem Command) zu speichern.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ahhhh. Das erklaert es.
Antworten