• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision6528 (tree)
Zeit2016-11-03 01:12:28
Autor(del#24082)

Log Message

チケット #34056 SCPダウンロードすると応答なしになる

SCPファイルの受信処理において、スレッドのメッセージキューの使用を廃止して、
代わりに独自のリンクドリスト方式に変更した。

Ändern Zusammenfassung

Diff

--- trunk/ttssh2/ttxssh/ssh.c (revision 6527)
+++ trunk/ttssh2/ttxssh/ssh.c (revision 6528)
@@ -84,6 +84,8 @@
8484
8585 static char ssh_ttymodes[] = "\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04";
8686
87+static CRITICAL_SECTION g_ssh_scp_lock; /* SCP受信用ロック */
88+
8789 static void try_send_credentials(PTInstVar pvar);
8890 static void prep_compression(PTInstVar pvar);
8991
@@ -122,7 +124,10 @@
122124 static void start_ssh_heartbeat_thread(PTInstVar pvar);
123125 void ssh2_channel_send_close(PTInstVar pvar, Channel_t *c);
124126 static BOOL SSH_agent_response(PTInstVar pvar, Channel_t *c, int local_channel_num, unsigned char *data, unsigned int buflen);
127+static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen);
128+static void ssh2_scp_free_packetlist(Channel_t *c);
125129
130+
126131 //
127132 // Global request confirm
128133 //
@@ -300,6 +305,8 @@
300305 CloseHandle(c->scp.thread);
301306 c->scp.thread = (HANDLE)-1L;
302307 }
308+
309+ ssh2_scp_free_packetlist(c);
303310 }
304311 if (c->type == TYPE_AGENT) {
305312 buffer_free(c->agent_msg);
@@ -8182,11 +8189,14 @@
81828189 if (is_canceled_window(hWnd))
81838190 goto cancel_abort;
81848191
8185- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
8192+ ssh2_scp_get_packetlist(c, &data, &buflen);
8193+ if (data && buflen) {
8194+ msg.message = WM_RECEIVING_FILE;
8195+
81868196 switch (msg.message) {
81878197 case WM_RECEIVING_FILE:
8188- data = (unsigned char *)msg.wParam;
8189- buflen = (unsigned int)msg.lParam;
8198+ //data = (unsigned char *)msg.wParam;
8199+ //buflen = (unsigned int)msg.lParam;
81908200 eof = 0;
81918201
81928202 if (c->scp.filercvsize >= c->scp.filetotalsize) { // EOF
@@ -8261,6 +8271,86 @@
82618271 return 0;
82628272 }
82638273
8274+static void ssh2_scp_add_packetlist(Channel_t *c, unsigned char *buf, unsigned int buflen)
8275+{
8276+ PacketList_t *p, *old;
8277+
8278+ EnterCriticalSection(&g_ssh_scp_lock);
8279+
8280+ // allocate new buffer
8281+ p = malloc(sizeof(PacketList_t));
8282+ if (p == NULL)
8283+ goto error;
8284+ p->buf = buf;
8285+ p->buflen = buflen;
8286+ p->next = NULL;
8287+
8288+ if (c->scp.pktlist_head == NULL) {
8289+ c->scp.pktlist_head = p;
8290+ c->scp.pktlist_tail = p;
8291+ }
8292+ else {
8293+ old = c->scp.pktlist_tail;
8294+ old->next = p;
8295+ c->scp.pktlist_tail = p;
8296+ }
8297+
8298+error:;
8299+ LeaveCriticalSection(&g_ssh_scp_lock);
8300+}
8301+
8302+static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen)
8303+{
8304+ PacketList_t *p;
8305+
8306+ EnterCriticalSection(&g_ssh_scp_lock);
8307+
8308+ if (c->scp.pktlist_head == NULL) {
8309+ *buf = NULL;
8310+ *buflen = 0;
8311+ goto end;
8312+ }
8313+
8314+ p = c->scp.pktlist_head;
8315+ *buf = p->buf;
8316+ *buflen = p->buflen;
8317+
8318+ c->scp.pktlist_head = p->next;
8319+
8320+ if (c->scp.pktlist_head == NULL)
8321+ c->scp.pktlist_tail = NULL;
8322+
8323+ free(p);
8324+
8325+end:;
8326+ LeaveCriticalSection(&g_ssh_scp_lock);
8327+}
8328+
8329+static void ssh2_scp_alloc_packetlist(Channel_t *c)
8330+{
8331+ c->scp.pktlist_head = NULL;
8332+ c->scp.pktlist_tail = NULL;
8333+ InitializeCriticalSection(&g_ssh_scp_lock);
8334+}
8335+
8336+static void ssh2_scp_free_packetlist(Channel_t *c)
8337+{
8338+ PacketList_t *p, *old;
8339+
8340+ p = c->scp.pktlist_head;
8341+ while (p) {
8342+ old = p;
8343+ p = p->next;
8344+
8345+ free(old->buf);
8346+ free(old);
8347+ }
8348+
8349+ c->scp.pktlist_head = NULL;
8350+ c->scp.pktlist_tail = NULL;
8351+ DeleteCriticalSection(&g_ssh_scp_lock);
8352+}
8353+
82648354 static BOOL SSH2_scp_fromremote(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen)
82658355 {
82668356 int permission;
@@ -8314,6 +8404,7 @@
83148404 ShowWindow(hDlgWnd, SW_SHOW);
83158405 }
83168406
8407+ ssh2_scp_alloc_packetlist(c);
83178408 thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_receive_thread, c, 0, &tid);
83188409 if (thread == (HANDLE)-1) {
83198410 // TODO:
@@ -8335,26 +8426,15 @@
83358426
83368427 } else if (c->scp.state == SCP_DATA) { // payloadの受信
83378428 unsigned char *newdata = malloc(buflen);
8338- BOOL ret;
8339- DWORD texit;
83408429 if (newdata != NULL) {
83418430 memcpy(newdata, data, buflen);
8342- do {
8343- // SCPファイル受信中に、ファイル受信を中断すると、無限ループに陥ることがあるため、
8344- // スレッドが終了しているかどうかを判別する。
8345- // (2014.7.6 yutaka)
8346- texit = STILL_ACTIVE;
8347- GetExitCodeThread(c->scp.thread, &texit);
8348- if (texit != STILL_ACTIVE) {
8349- texit = texit;
8350- break;
8351- }
83528431
8353- // スレッドがキューを作っていない場合、メッセージポストが失敗することがあるので、
8354- // 無限リトライする。MSDNにそうしろと書いてある。
8355- // (2011.6.15 yutaka)
8356- ret = PostThreadMessage(c->scp.thread_id, WM_RECEIVING_FILE, (WPARAM)newdata, (LPARAM)buflen);
8357- } while (ret == FALSE);
8432+ // SCP受信処理のスピードが速い場合、スレッドのメッセージキューがフル(10000個)に
8433+ // なり、かつスレッド上での SendMessage がブロックすることにより、Tera Term(TTSSH)
8434+ // 自体がストールしてしまう。この問題を回避するため、スレッドのメッセージキューを
8435+ // 使うのをやめて、リンクドリスト方式に切り替える。
8436+ // (2016.11.3 yutaka)
8437+ ssh2_scp_add_packetlist(c, newdata, buflen);
83588438 }
83598439
83608440 } else if (c->scp.state == SCP_CLOSING) { // EOFの受信
--- trunk/ttssh2/ttxssh/ssh.h (revision 6527)
+++ trunk/ttssh2/ttxssh/ssh.h (revision 6528)
@@ -750,6 +750,12 @@
750750 struct bufchain *next;
751751 } bufchain_t;
752752
753+typedef struct PacketList {
754+ char *buf;
755+ unsigned int buflen;
756+ struct PacketList *next;
757+} PacketList_t;
758+
753759 typedef struct scp {
754760 enum scp_dir dir; // transfer direction
755761 enum scp_state state; // SCP state
@@ -767,6 +773,8 @@
767773 long long filercvsize;
768774 DWORD filemtime;
769775 DWORD fileatime;
776+ PacketList_t *pktlist_head;
777+ PacketList_t *pktlist_tail;
770778 } scp_t;
771779
772780 enum sftp_state {
Show on old repository browser