From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11747 invoked from network); 6 Oct 2002 07:28:49 -0000 Received: from unknown (HELO monty-python.gnu.org) (199.232.76.173) by sources.redhat.com with SMTP; 6 Oct 2002 07:28:49 -0000 Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 17y5pf-00005G-00; Sun, 06 Oct 2002 03:28:08 -0400 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 17y5ol-0007D0-00 for gnats-prs@gnu.org; Sun, 06 Oct 2002 03:27:11 -0400 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 17y5oZ-0006kn-00 for gnats-prs@gnu.org; Sun, 06 Oct 2002 03:27:04 -0400 Received: from fencepost.gnu.org ([199.232.76.164]) by monty-python.gnu.org with esmtp (Exim 4.10) id 17y5oV-0006et-00; Sun, 06 Oct 2002 03:26:55 -0400 Received: from gnats by fencepost.gnu.org with local (Exim 4.10) id 17y5oV-0000ys-00; Sun, 06 Oct 2002 03:26:55 -0400 From: vkarasik@ndsisrael.com To: pdm-gnats@zamazal.org,gnats-prs@gnu.org,bug-gnats@gnu.org Reply-To: vkarasik@ndsisrael.com Subject: misc/423: Problem when using AIO sockets Message-Id: Sender: gnats-prs-admin@gnu.org Errors-To: gnats-prs-admin@gnu.org X-BeenThere: gnats-prs@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Copies of bug tracking system messages List-Archive: Date: Sun, 06 Oct 2002 00:28:00 -0000 X-SW-Source: 2002-q4/txt/msg00003.txt.bz2 >Number: 423 >Category: misc >Synopsis: Problem when using AIO sockets >Confidential: no >Severity: critical >Priority: high >Responsible: unassigned >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Sun Oct 06 03:26:54 -0400 2002 >Originator: Vitaly Karasik >Release: glibc 2.2.4-13, 2.2.5-37, 2.2.93-5 >Organization: NDS >Environment: different HP Vectra's with RH7.2,7.3,8.0 >Description: i've attached a program [written by Steve Huston shuston@riverace.com] which is only C/C++ (no ACE) and reproduces the problem with AIO on Linux. It has compilation instructions in it. This program opens a socket back to itself - there's a client and server. The client sends some data; the server reads it and sends it back. When the client receives the echo, it starts the process over again, counting how many times it goes around. There is one command line argument - the number of iterations to run through. On each successful iteration, the client prints a "." to the terminal. If it completes all of the iterations, it exits. If it goes for more than 2 seconds with no AIO activity, it will print an error message and sleep for 5 minutes. This gives you an opportunity to attach to it with gdb and examine the threads. One will be stuck in libc_read, and if you also do a "netstat" you'll see there is data available to read, but it's not being read. This is the same condition we see in ACE. It won't run correctly in gdb - it runs the machine out of threads and runs very slowly. This is why you need to wait for it to lock up and then attach to it. >How-To-Repeat: 1. g++ -g -o aiotest -lrt aiotest.cpp 2. run "./aiotest 1000000" few times Actual Results: many times I get "Resorce temporarily unavailable" Expected Results: "AIOCB test successful" >Fix: Unknown >Unformatted: ----gnatsweb-attachment---- Content-Type: text/plain; name="aiotest.cpp" Content-Disposition: inline; filename="aiotest.cpp" // ============================================================================ // // = LIBRARY // proactor // // = FILENAME // aiotest.cpp // // = DESCRIPTION // Checkout $ACE_ROOT/examples/Reactor/Proactor/test_aiocb_ace.cpp, // which is the ACE'ified version of this program. // // = COMPILE and RUN // % g++ -g -o aiotest -lrt aiotest.cpp // % ./aiotest // // = AUTHOR // Steve Huston // // ============================================================================ #include #include #include #include #include #include #include #include #include #include class Test_Aio { public: Test_Aio (void) : nr_recvd_ (0) {}; // Set up the socket and AIOCBs int init (void); // Doing the testing stuff. int do_aio (int iterations); ~Test_Aio (void); private: // Server socket. int server_; // Server receive and echo operations struct aiocb server_in_; struct aiocb server_out_; char server_in_buff_[128]; char server_out_buff_[128]; // Client socket int client_; // Client send and receive operations struct aiocb client_in_; struct aiocb client_out_; char client_in_buff_[128]; char client_out_buff_[128]; int nr_recvd_; }; Test_Aio::~Test_Aio (void) { close (this->server_); close (this->client_); } // Set up the sockets. int Test_Aio::init (void) { sockaddr_in pick_a_port; // Helpers to avoid lots of casting sockaddr * addr = (sockaddr *)&pick_a_port; socklen_t addrlen = (socklen_t)(sizeof pick_a_port); int listener = socket (PF_INET, SOCK_STREAM, 0); memset (&pick_a_port, 0, sizeof pick_a_port); if (bind (listener, addr, addrlen) == -1) { perror ("bind"); return -1; } getsockname (listener, addr, &addrlen); if (listen (listener, 1) == -1) { perror ("listen"); return -1; } this->client_ = socket (PF_INET, SOCK_STREAM, 0); if (connect (this->client_, addr, addrlen) == -1) { perror ("connect"); return -1; } if ((this->server_ = accept (listener, 0, 0)) == -1) { perror ("accept"); return -1; } memset (this->server_in_buff_, 0, sizeof (this->server_in_buff_)); memset (this->server_out_buff_, 0, sizeof (this->server_out_buff_)); memset (this->client_in_buff_, 0, sizeof (this->client_in_buff_)); memset (this->client_out_buff_, 0, sizeof (this->client_out_buff_)); close (listener); return 0; } // Start the initial client send and server receive. Whatever the server // receives, it sends back. Continue until have completed // or 2 seconds goes by without any activity. int Test_Aio::do_aio (int iterations) { struct aiocb *list_aiocb[4]; enum { SRV_IN = 0, SRV_OUT, CLI_IN, CLI_OUT }; list_aiocb[SRV_IN] = 0; list_aiocb[SRV_OUT] = 0; list_aiocb[CLI_IN] = 0; list_aiocb[CLI_OUT] = 0; this->server_in_.aio_fildes = this->server_; this->server_in_.aio_offset = 0; this->server_in_.aio_buf = this->server_in_buff_; this->server_in_.aio_nbytes = sizeof (this->server_in_buff_); this->server_in_.aio_reqprio = 0; this->server_in_.aio_sigevent.sigev_notify = SIGEV_NONE; this->server_in_.aio_sigevent.sigev_signo = 0; this->server_in_.aio_sigevent.sigev_value.sival_ptr = 0; this->server_out_.aio_fildes = this->server_; this->server_out_.aio_offset = 0; this->server_out_.aio_buf = this->server_out_buff_; this->server_out_.aio_nbytes = 0; // Fill in when receive length known this->server_out_.aio_reqprio = 0; this->server_out_.aio_sigevent.sigev_notify = SIGEV_NONE; this->server_out_.aio_sigevent.sigev_signo = 0; this->server_out_.aio_sigevent.sigev_value.sival_ptr = 0; this->client_in_.aio_fildes = this->client_; this->client_in_.aio_offset = 0; this->client_in_.aio_buf = this->client_in_buff_; this->client_in_.aio_nbytes = sizeof (this->client_in_buff_); this->client_in_.aio_reqprio = 0; this->client_in_.aio_sigevent.sigev_notify = SIGEV_NONE; this->client_in_.aio_sigevent.sigev_signo = 0; this->client_in_.aio_sigevent.sigev_value.sival_ptr = 0; this->client_out_.aio_fildes = this->client_; this->client_out_.aio_offset = 0; this->client_out_.aio_buf = this->client_out_buff_; strcpy (this->client_out_buff_, "This is a test of Linux AIO\n"); this->client_out_.aio_nbytes = strlen (this->client_out_buff_); this->client_out_.aio_reqprio = 0; this->client_out_.aio_sigevent.sigev_notify = SIGEV_NONE; this->client_out_.aio_sigevent.sigev_signo = 0; this->client_out_.aio_sigevent.sigev_value.sival_ptr = 0; // Initiate the client's first write and server's first read if (aio_write (&this->client_out_) == -1) { perror ("client initial write"); return -1; } list_aiocb[CLI_OUT] = &this->client_out_; if (aio_read (&this->server_in_) == -1) { perror ("server initial read"); return -1; } list_aiocb[SRV_IN] = &this->server_in_; // Wait for the completion on aio_suspend. // The structure of send/receive for client and server are different // to try and poke holes in AIO. // When: // the server completes a write, note it. // the server completes a read, start a write and the next read. // the client completes a write, start another read. // the client completes a read, start a write. int return_val = 0; while (this->nr_recvd_ < iterations) { struct timespec timeout; timeout.tv_sec = 2; timeout.tv_nsec = 0; return_val = aio_suspend (list_aiocb, 4, &timeout); if (return_val == -1) { perror ("aio_suspend"); sleep(300); break; } // Analyze return and error values. As soon as something completes, // start the corresponding operation. if (list_aiocb[SRV_OUT] && aio_error (list_aiocb [SRV_OUT]) != EINPROGRESS) { return_val = aio_return (list_aiocb [SRV_OUT]); if (return_val <= 0) // Socket close or error { perror ("server write"); break; } list_aiocb[SRV_OUT] = 0; // Done; remove from dispatch } if (list_aiocb[SRV_IN] && aio_error (list_aiocb [SRV_IN]) != EINPROGRESS) { return_val = aio_return (list_aiocb [SRV_IN]); if (return_val <= 0) // Socket close or error { perror ("server read"); break; } // Data read; send it back and restart the read. strncpy (this->server_out_buff_, this->server_in_buff_, return_val); this->server_out_.aio_nbytes = return_val; if (aio_write (&this->server_out_) == -1) { perror ("server aio_write"); break; } list_aiocb[SRV_OUT] = &this->server_out_; // Let aio_suspend see it if (aio_read (&this->server_in_) == -1) { perror ("server aio_read"); break; } } if (list_aiocb[CLI_OUT] && aio_error (list_aiocb [CLI_OUT]) != EINPROGRESS) { return_val = aio_return (list_aiocb [CLI_OUT]); if (return_val <= 0) // Socket close or error { perror ("client write"); break; } list_aiocb[CLI_OUT] = 0; // Done; remove from dispatch // Data sent; prepare to receive the echo if (aio_read (&this->client_in_) == -1) { perror ("client aio_read"); break; } list_aiocb[CLI_IN] = &this->client_in_; // Let aio_suspend see it } if (list_aiocb[CLI_IN] && aio_error (list_aiocb [CLI_IN]) != EINPROGRESS) { return_val = aio_return (list_aiocb [CLI_IN]); if (return_val <= 0) // Socket close or error { perror ("client read"); break; } cout << "."; ++this->nr_recvd_; list_aiocb[CLI_IN] = 0; // Done; remove from dispatch // Data received; start another pass if (aio_write (&this->client_out_) == -1) { perror ("client aio_write"); break; } list_aiocb[CLI_OUT] = &this->client_out_; // Let aio_suspend see it } } if (this->nr_recvd_ < iterations) { cerr << "Oops; only did " << this->nr_recvd_ << " of " << iterations << " iterations." << endl; return -1; } cout << iterations << " iterations done." << endl; return 0; } int main (int argc, char **argv) { Test_Aio test_aio; int iterations = 1000; if (argc > 1) iterations = atoi (argv[1]); if (test_aio.init () != 0) { printf ("AIOCB test failed:\n" "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"); return -1; } if (test_aio.do_aio (iterations) != 0) { printf ("AIOCB test failed:\n" "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"); return -1; } printf ("AIOCB test successful:\n" "ACE_POSIX_AIOCB_PROACTOR should work in this platform\n"); return 0; } _______________________________________________ Gnats-prs mailing list Gnats-prs@gnu.org http://mail.gnu.org/mailman/listinfo/gnats-prs