Closed tianrenz2 closed 3 days ago
Here is a script below that could quickly reproduce this issue, when you see any socket connect error output, then it's likely the bug happens, replace xxxxxxx based on your environment :)
Another possible prerequisite: on each reconnect, the iscsi target should return SCSI_STATUS_REDIRECT on the login thus invoke the second connection establishment.
#include <iscsi/iscsi.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
// Function executed by the iSCSI thread
void *iscsi_thread(void *arg) {
struct iscsi_context *iscsi;
char *target = "xxxxxxx";
char *initiator = "xxxxxxxx";
struct iscsi_url *iscsi_url;
iscsi = iscsi_create_context(initiator);
iscsi_url = iscsi_parse_full_url(iscsi, "xxxxxxx");
iscsi_set_targetname(iscsi, iscsi_url->target);
iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
iscsi_set_timeout(iscsi, 5);
iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun);
while (1) {
iscsi_reconnect_sync(iscsi);
}
return NULL;
}
// Function executed by the open file thread
void *file_thread(void *arg) {
while (1) {
int fd = open("xxxxxxxxx", O_CREAT | O_RDWR, 0644);
if (fd == -1) {
perror("[Thread 2] Error opening file");
} else {
// printf("[Thread 2] File opened successfully (fd: %d)\n", fd);
close(fd);
}
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
// Create iSCSI reconnect thread
if (pthread_create(&thread1, NULL, iscsi_thread, NULL) != 0) {
perror("Failed to create iSCSI thread");
return 1;
}
// Create file opening thread
if (pthread_create(&thread2, NULL, file_thread, NULL) != 0) {
perror("Failed to create file thread");
return 1;
}
// Wait for threads to finish (infinite loop in this case)
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
Merged. Thanks!
On reconnect case, the iscsi_tcp_connect tries to reuse the fd number of old_iscsi. However, this fd could have been already closed in previous iscsi_tcp_disconnect if iscsi->fd == iscsi->old_iscsi->fd and the fd number might have been allocated to some other caller, in this case the fd reuse in iscsi_tcp_connect is not safe anymore.
Solve this by not closing the fd if iscsi and old_iscsi share the same fd on reconnect to "really" reserve this fd number.