Was kann ein SIGPWR-Signal auslösen, das einen "sendmsg" -Systemaufruf unterbricht?

949
Sotirios Delimanolis

Auf einem RHEL 6-Host habe ich einen Cassandra-Server, der auf localhost auf TCP-Verbindungen wartet. Parallel dazu habe ich eine Client-Anwendung, die Anfragen sendet. Der Client (C # Mono) sendmsgsendet die serialisierten Bytes.

Ich sehe sendmsgständig die Rückgabe, ohne alle angeforderten Bytes gesendet zu haben. Ich habe straceversucht, das zu debuggen

sudo strace -p<pid> -s 100 -f -tt &> tmp.out 

und Säge (gefilterte Probe für ein Gewindegang 47605)

[pid 47605] 16:32:13.388307 sendmsg(8,, {"3490_3491_3492_3493_3494_3495_3496_3497_3498_3499_3500_3501_3502_3503_3504_3505_3506_3507_3508_3509_"..., 7553}], msg_controllen=0, msg_flags=0}, 0 <unfinished ...> [pid 46142] 16:32:13.413922 tgkill(46142, 47605, SIGPWR) = 0 [pid 47605] 16:32:13.414024 <... sendmsg resumed> ) = 16384 [pid 47605] 16:32:13.414094 --- SIGPWR (Power failure) @ 0 (0) --- [pid 47605] 16:32:13.414191 rt_sigprocmask(SIG_BLOCK, [XCPU], <unfinished ...> [pid 47605] 16:32:13.414242 <... rt_sigprocmask resumed> NULL, 8) = 0 [pid 47605] 16:32:13.414304 rt_sigsuspend(~[XCPU RTMIN RT_1] <unfinished ...> [pid 46142] 16:32:13.418930 tgkill(46142, 47605, SIGXCPU) = 0 [pid 47605] 16:32:13.419057 <... rt_sigsuspend resumed> ) = ? ERESTARTNOHAND (To be restarted) [pid 47605] 16:32:13.419143 --- SIGXCPU (CPU time limit exceeded) @ 0 (0) --- [pid 47605] 16:32:13.419236 rt_sigreturn(0x30 <unfinished ...> [pid 47605] 16:32:13.419306 <... rt_sigreturn resumed> ) = -1 EINTR (Interrupted system call) [pid 47605] 16:32:13.419360 rt_sigprocmask(SIG_UNBLOCK, [XCPU], <unfinished ...> [pid 47605] 16:32:13.419431 <... rt_sigprocmask resumed> NULL, 8) = 0 [pid 47605] 16:32:13.419481 rt_sigreturn(0xffffffff <unfinished ...> [pid 47605] 16:32:13.419562 <... rt_sigreturn resumed> ) = 16384 

Dies scheint darauf hinzudeuten, dass Thread mit TID 46142verwendet wurde tgkill, um ein SIGPWR-Signal an Thread mit Tid zu senden, 47605der gerade Bytes mit sendete sendmsg. Dies unterbrach es irgendwie und es wurden lediglich 16384 der 23937 Bytes angefordert.

Ich habe versucht zu sehen, ob der Thread mit tid 46142irgendetwas tut, das die Ursache des Problems erklären könnte tgkill, aber alles, was ich sehe, ist

[pid 46142] 16:32:13.370983 futex(0x34af8d0, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...> [pid 46142] 16:32:13.371061 <... futex resumed> ) = -1 EAGAIN (Resource temporarily unavailable) [pid 46142] 16:32:13.371169 futex(0x34af8d0, FUTEX_WAKE_PRIVATE, 1 <unfinished ...> [pid 46142] 16:32:13.371221 <... futex resumed> ) = 0 [pid 46142] 16:32:13.377014 brk(0x3d45000 <unfinished ...> [pid 46142] 16:32:13.377254 <... brk resumed> ) = 0x3d45000 [pid 46142] 16:32:13.378971 mmap(0x40696000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0) = 0x40696000 [pid 46142] 16:32:13.381868 futex(0x7feb0000b88c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7feb0000b888, ) = 1 [pid 46142] 16:32:13.413922 tgkill(46142, 47605, SIGPWR) = 0 [pid 46142] 16:32:13.413992 tgkill(46142, 47599, SIGPWR <unfinished ...> [pid 46142] 16:32:13.414221 <... tgkill resumed> ) = 0 [pid 46142] 16:32:13.414267 tgkill(46142, 46146, SIGPWR <unfinished ...> [pid 46142] 16:32:13.414437 <... tgkill resumed> ) = 0 [pid 46142] 16:32:13.414601 futex(0x1b1e320, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...> [pid 46142] 16:32:13.414718 <... futex resumed> ) = 0 [pid 46142] 16:32:13.414767 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7feb19800000 

was ich im Zusammenhang mit dem Aufruf des Netzwerksystems nicht verstehen kann.

Was könnte dazu führen, dass ein Thread ein SIGPWR-Signal sendet?


Ich bin nicht sicher, ob dies relevant ist, aber ich verwende eine Socket-Sendepuffergröße von 4096, und die MTU-Größe der Loopback-Schnittstelle ist auf 16436 festgelegt. Ich kann den Teil sendmsgmit diesen Größen konsistent reproduzieren . Wenn ich jedoch die MTU-Größe verdopple, geht das Problem weg. Ebenso kann ich das Problem nicht mehr reproduzieren, wenn ich die Sendepuffergröße meines Socket auf etwas sehr viel größer als 24000 gesetzt habe.

2

1 Antwort auf die Frage

1
grawity

Alles, was Threads tun, ist nur ein Teil des eigenen Codes oder einer von ihm verwendeten Bibliothek. Die Antwort auf "Was könnte einen Thread veranlassen, ein SIGPWR-Signal zu senden?" wird von Programm zu Programm variieren.

In Ihrem Fall ist es die Mono-Laufzeit, die diese intern verwendet. Soweit ich herausfinden konnte, werden SIGPWR und SIGXCPU verwendet, um den Garbage Collector auszulösen .

Danke für den Fund. Das klingt für die von mir verwendete Version von Mono korrekt. Ist sendmsg etwas Besonderes in der Art und Weise, wie der ausführende Thread ein Signal verarbeitet? Die Manpage schien das Szenario, in dem sie bereits mit dem Senden begonnen hat, nicht zu behandeln. (Auch eine Idee, warum die MTU einen Unterschied machen würde?) Sotirios Delimanolis vor 7 Jahren 0