From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2122.outbound.protection.outlook.com [40.107.223.122]) by sourceware.org (Postfix) with ESMTPS id 8156C3857817 for ; Fri, 3 Sep 2021 19:53:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8156C3857817 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=cornell.edu Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cornell.edu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=AsnuJCbhjAjGF52s5VI6xtBRwc/waM/7W+swA3mn6LBg6/lEcgOpAY7T+AW5nWoKiXLweQFGvRRQEgwXqGlWO9lEYOxdqf2R+ZznDHSpPMXqi2mYc3LxQl6XZ2OHox4JVN8YT59o/QNEmyaqlGAVB80Xt37njC64VqvDKtbHtoTIbwmmvbtCr6xclhwRO7rDDHucUKnej9ZOoilZui8+C0HN6DcXsjEMybBVIk0i923rAZVy5sNWq3zfZnNbz7J1h0yjVhas5I8EtjI38POWxSiruL/bGwCp3hUh1+BLZWaGpQvXFucRoof87qGAbwPpjQsUYtynDfV2tgidRbKPYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=9/Xgb8U7xJ+ERik/3R8eWqfmqaeukg8q5rba4LPMYd4=; b=e93v/9ohFcDs/4ITaTHbR42U/qo+qs57hWRcPnkNqS/8sNRz66cNgiRAtqUkdAvPrDJmmHR+Fh6MuZNIH5miwzzHaBL0BHDHMRyFuZaxXN1QP9YbWbwu1YMZQjjkEJuBrrc/koM7qzo/iEMkAjTV7lpF1HS+xN/zB0X46FSSxmXGFJ9el3ooVMMfTsVE9vAuPdy+0UYa1Y1WqWgYlkz66s/YpwTX/ms8AL2ijimdqWm1OS6e1ESTc3avY2vhs65zKX0pb9YY6RFUi3qMAcIBxxhs0cGX0XubCBQSRRZtxuP1MivRi657mVsH8JC8Iu5knxXRsXUmFtgKIkIOyiGZzw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=cornell.edu; dmarc=pass action=none header.from=cornell.edu; dkim=pass header.d=cornell.edu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cornell.edu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9/Xgb8U7xJ+ERik/3R8eWqfmqaeukg8q5rba4LPMYd4=; b=EDxzsT4DNIESt3sT5seWVQsD3q1bEzyOEsVTzQRwKOieqH/EBjImUxwZoozPlwiCQS1umlokomCQFfwlasuKaiFvVJ3rdSdEhf1W6dtvHrLI5O9V5AG2o9KItrKrDGwtAOWbkSZyhls1Ovi9GW8Ie2Do6Bfw/rV1h9rEiJn9EbA= Authentication-Results: cygwin.com; dkim=none (message not signed) header.d=none;cygwin.com; dmarc=none action=none header.from=cornell.edu; Received: from BN7PR04MB4388.namprd04.prod.outlook.com (2603:10b6:406:f8::19) by BN7PR04MB4052.namprd04.prod.outlook.com (2603:10b6:406:c0::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4478.19; Fri, 3 Sep 2021 19:53:11 +0000 Received: from BN7PR04MB4388.namprd04.prod.outlook.com ([fe80::b510:889b:1fd0:d80e]) by BN7PR04MB4388.namprd04.prod.outlook.com ([fe80::b510:889b:1fd0:d80e%7]) with mapi id 15.20.4478.020; Fri, 3 Sep 2021 19:53:11 +0000 Subject: Re: cygrunsrv + sshd + rsync = 20 times too slow -- throttled? To: cygwin-developers@cygwin.com References: <20210901172339.1039604b7067e0492534a20f@nifty.ne.jp> <24138e20-aa97-cfea-bf48-198fc67755ea@cornell.edu> <9ba687eb-f4a0-18f8-b10b-76e7e51e123e@cornell.edu> <152bfc0c-2f72-c684-6fc5-aa7c36c136b8@cornell.edu> From: Ken Brown Message-ID: Date: Fri, 3 Sep 2021 15:53:10 -0400 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 In-Reply-To: Content-Type: multipart/mixed; boundary="------------CE8C8377AFA9E856C5F6F72E" Content-Language: en-US X-ClientProxiedBy: CH0PR08CA0028.namprd08.prod.outlook.com (2603:10b6:610:33::33) To BN7PR04MB4388.namprd04.prod.outlook.com (2603:10b6:406:f8::19) MIME-Version: 1.0 Received: from [IPv6:2603:7081:7e3f:3419:4172:b7ad:cdf5:53cb] (2603:7081:7e3f:3419:4172:b7ad:cdf5:53cb) by CH0PR08CA0028.namprd08.prod.outlook.com (2603:10b6:610:33::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4478.19 via Frontend Transport; Fri, 3 Sep 2021 19:53:10 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 53a63d25-e394-4300-f4c6-08d96f147576 X-MS-TrafficTypeDiagnostic: BN7PR04MB4052: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5797; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 1wHBoyeK77qM/GO5c2qt1JEyrzarfmu4a6/81wCog8xAWQ4gJAWEvs+OEoirBzPR9HcVpOzMOvY1cLsgAGljHJVczWwz+Tzo1oooosn8aS+NMtoaDUdg1oreWAoUG6pg/8L+dNO6bAO/CDWz+HBp6xjZpghY9i8s3XVcVQUAEteWB4NNVlQQBwfu3xN2zQ1Y46QlKCoXymNYkS3fjGjRnCpItYpbpyzIew4hOUjz597TB/vj3wGbC9tbg9DbrgTMUxXgzKAUliba9TNNiQWmopvyl59V+/8zLKHFXABTpyAu6VaF+Yjskk9apFf3ukiglMaHwadcC2kTwrXpgXg8XdbuNhALFqW9B7BDZXoBqZt6sTbCv7fODntcVBnArX1k7Qcl+eoqEoqXb2r8sOU1QXWI8XUVjGsJiNwgLJ979eTm2kdM2M4YJt62G0S4Ka8r8WCr5HoI2penI4v0TDVXMKCRrL5wZA5F+cL2s5OuEdHg1Py0nX3a2In4pZCbkbE4RwlQkJ0qrB8zQf7CXUBPiKSrjH8OV9/4SA8rpzArfUuMwSfXKkvtO+nK+D6GjBHTOZHWYrgGUyGe+2vVquMFDuwHPc+oJZ0eU/YtKdMtRpebmkp+9tzTRD3H/8ipn42/WlGCfzrqIqlWbmEHKUG92It0AzHyJVkz4BDgg0GV2PEejwxn+uJmXkJ/6rDZqDjIjAW5gb7fXuo8nqwBuyS8cHrT4adUCcLPg+ECmerepxM= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:BN7PR04MB4388.namprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(366004)(8676002)(36756003)(2906002)(2616005)(86362001)(8936002)(66556008)(31696002)(186003)(5660300002)(235185007)(38100700002)(66476007)(53546011)(6486002)(6916009)(31686004)(508600001)(316002)(66946007)(66616009)(75432002)(33964004)(43740500002)(45980500001); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?Windows-1252?Q?IcJjPUrBsW/T017iT/pGl7+49Q4xAOID5xJDtNGVLa3xBf+W4NmeHTmS?= =?Windows-1252?Q?3foylwfpXkoCKfNDt24yAZbrGYek5uoHRkIqUR5GvCcCo913nnheOmir?= =?Windows-1252?Q?xQZ4dQKPbo3gB8lQ3AiTqtUzDetIxUEYgI41J6SVU37PN1K2qGN5e22Z?= =?Windows-1252?Q?WlW/on2n5RiIldtWYVfgqZe1h+FSbrR3IZBWE61BIHqns8fQuJKNGz2b?= =?Windows-1252?Q?Qbx/B88y3Zp3dpFTY2E56UoPBN5IUQP4RwHNTh9TPJJzLeVtwgV/MeXw?= =?Windows-1252?Q?pvmtDZPzFFsJeZs9rpTZVljRAfYQuYrd6UhsLD8iG/iKQXdJTKE7fTRr?= =?Windows-1252?Q?Cdw0WoKrZECkBwKoQe9P9PsvYupnWn2Mq5hK7D41Es3uK5iqIlYs3dp3?= =?Windows-1252?Q?Rktt8KuRmDUQjvYKYLSTeJ9LIUmyJmZ4Dr2GYUdnjvbdExX1FGtf9mVs?= =?Windows-1252?Q?VqGoZGITklYajEgkMau1+MHqxqc6YIzPk0YFHUh/2Pyvhwg99gtn5njs?= =?Windows-1252?Q?C5lVUjz2iEMr+KB1W8CXMVEEcm0rlfsNKTfiKAccmAc5sj5ZSW7fPFJI?= =?Windows-1252?Q?a1NRWr17qV36owJkOFGHMsViSLf9idLDAhuxr+FcURFpe/fjyr7pAbfh?= =?Windows-1252?Q?/zSGb4vWVRb+n/cX5pHF3DuVergxW/BObjRvm8xbOi3SMzqysi9u17/B?= =?Windows-1252?Q?Sxj1Ouw5Lrvh1Zax9Q55rUPNuvW5FZ7MHwczhVRoldR18KtpG+t6Fa7T?= =?Windows-1252?Q?DRAHgUFPeFOhU+RbdN/usIgZN0GI2jHbXQ8NCV8T6gMx0zNnNGg75vfl?= =?Windows-1252?Q?GLYZDW/5NK+O77rvq4UZPq5YlTzNhcYGRiOLfP7e1j04pDb9qYspwupl?= =?Windows-1252?Q?Ecerh2lG0YHQjA//rJvaw/gxN759gzUUdbdRFuYfrNfwBOWGgnu2WC9d?= =?Windows-1252?Q?iiXV7aO3j8RWdQHp1JTUxWE03J47atSuz9gRpqt2vSaR68axahBZKLMw?= =?Windows-1252?Q?tHzYqPrWY7MvAKDhUwieW8LSe5nqD5luElIisryitg8n/O2n8R6KGb1L?= =?Windows-1252?Q?j+0QT8TwvLSy1gXSLiF5jC0DbEqkzxj2FJl55IfmzHPTCNbORlNhw7S2?= =?Windows-1252?Q?n220zEjLWH+UM7owC4c8KkWI99C6crnsie01fsH0vIfus9B0X4co51V7?= =?Windows-1252?Q?7F6LbFwKvI5qGjm4BWVO+ole32O3aJDoEFb3FHodMj898DU8aENvutIK?= =?Windows-1252?Q?31Cn5gyqrR5YaUnWXFTmgay9DO/eevaMF5e2/fI6927N+wO6Jrp2pLEZ?= =?Windows-1252?Q?ffMkxJ7iIp1yxuaNjGpQkUM6ZXlzpJlrYmieIPl7T4/IGi9T0NGRSfmV?= =?Windows-1252?Q?EuQcFJwpeXkArHh7dz5s1G2roQbxzEVvXIfBCrH7GHOeSy5Q0oJuCe79?= =?Windows-1252?Q?WfJnLgodcKn4lsCXPm9CYy3w0JYO/cVtw0cs5nyHg4tg1pTPt80hodio?= =?Windows-1252?Q?quvEzUjG?= X-OriginatorOrg: cornell.edu X-MS-Exchange-CrossTenant-Network-Message-Id: 53a63d25-e394-4300-f4c6-08d96f147576 X-MS-Exchange-CrossTenant-AuthSource: BN7PR04MB4388.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Sep 2021 19:53:11.3163 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 5d7e4366-1b9b-45cf-8e79-b14b27df46e1 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 5Mk2D6rSxmHNOWhn5tHphaV4yUo5hwFHmBGd+lgT5ZzcSBLxrzWGvjh77+675EUmE9dYBGpr/pJVrGnXBWflgw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN7PR04MB4052 X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_STATUS, MSGID_FROM_MTA_HEADER, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: cygwin-developers@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component developers mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Sep 2021 19:53:17 -0000 --------------CE8C8377AFA9E856C5F6F72E Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit On 9/3/2021 3:00 PM, Ken Brown wrote: > On 9/3/2021 5:12 AM, Corinna Vinschen wrote: >> I pushed my stuff to the topic/pipe branch split into hopefully useful >> chunks.  Kick me if anything is wrong or not working. > > Some of the bugs you fixed in the pipe code exist in the fifo code also.  I > started going through them and fixing them, but then I realized that > fhandler_pipe::raw_write and fhandler_fifo::raw_write are identical.  For ease > of maintenance, I'm thinking we should have a single function, say > fhandler_base::raw_write_pipe or fhandler_base::raw_write_pipe_fifo, which is > called by both of them. > > WDYT? Here's what that would look like (attached). Ken --------------CE8C8377AFA9E856C5F6F72E Content-Type: text/plain; charset=UTF-8; name="0001-wip.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0001-wip.patch" >From 108a50006decade6dca0b91ca6f1c165bdfd20dd Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Fri, 3 Sep 2021 15:43:17 -0400 Subject: [PATCH 1/2] wip --- winsup/cygwin/fhandler.cc | 124 +++++++++++++++++++++++++++++++++ winsup/cygwin/fhandler.h | 6 +- winsup/cygwin/fhandler_fifo.cc | 98 +------------------------- winsup/cygwin/fhandler_pipe.cc | 121 +------------------------------- 4 files changed, 130 insertions(+), 219 deletions(-) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index f0c1b68f1..7d7aad216 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -280,6 +280,129 @@ fhandler_base::raw_write (const void *ptr, size_t len) return io.Information; } +#define STATUS_PIPE_IS_CLOSED(status) \ + ({ NTSTATUS _s = (status); \ + _s == STATUS_PIPE_CLOSING \ + || _s == STATUS_PIPE_BROKEN \ + || _s == STATUS_PIPE_EMPTY; }) + +/* Used by fhandler_pipe::raw_write and fhandler_fifo::raw_write. */ +ssize_t __reg3 +fhandler_base::raw_write_pipe_fifo (const void *ptr, size_t len) +{ + size_t nbytes = 0; + ULONG chunk; + NTSTATUS status = STATUS_SUCCESS; + IO_STATUS_BLOCK io; + HANDLE evt = NULL; + + if (!len) + return 0; + + if (len <= max_atomic_write) + chunk = len; + else if (is_nonblocking ()) + chunk = len = max_atomic_write; + else + chunk = max_atomic_write; + + /* Create a wait event if the pipe or fifo is in blocking mode. */ + if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL))) + { + __seterrno (); + return -1; + } + + /* Write in chunks, accumulating a total. If there's an error, just + return the accumulated total unless the first write fails, in + which case return -1. */ + while (nbytes < len) + { + ULONG_PTR nbytes_now = 0; + size_t left = len - nbytes; + ULONG len1; + DWORD waitret = WAIT_OBJECT_0; + + if (left > chunk) + len1 = chunk; + else + len1 = (ULONG) left; + /* NtWriteFile returns success with # of bytes written == 0 if writing + on a non-blocking pipe fails because the pipe buffer doesn't have + sufficient space. + + POSIX requires + - A write request for {PIPE_BUF} or fewer bytes shall have the + following effect: if there is sufficient space available in the + pipe, write() shall transfer all the data and return the number + of bytes requested. Otherwise, write() shall transfer no data and + return -1 with errno set to [EAGAIN]. + + - A write request for more than {PIPE_BUF} bytes shall cause one + of the following: + + - When at least one byte can be written, transfer what it can and + return the number of bytes written. When all data previously + written to the pipe is read, it shall transfer at least {PIPE_BUF} + bytes. + + - When no data can be written, transfer no data, and return -1 with + errno set to [EAGAIN]. */ + while (len1 > 0) + { + status = NtWriteFile (get_handle (), evt, NULL, NULL, &io, + (PVOID) ptr, len1, NULL, NULL); + if (evt || !NT_SUCCESS (status) || io.Information > 0 + || len <= PIPE_BUF) + break; + len1 >>= 1; + } + if (evt && status == STATUS_PENDING) + { + waitret = cygwait (evt); + if (waitret == WAIT_OBJECT_0) + status = io.Status; + } + if (waitret == WAIT_CANCELED) + status = STATUS_THREAD_CANCELED; + else if (waitret == WAIT_SIGNALED) + status = STATUS_THREAD_SIGNALED; + else if (isclosed ()) /* A signal handler might have closed the fd. */ + { + if (waitret == WAIT_OBJECT_0) + set_errno (EBADF); + else + __seterrno (); + } + else if (NT_SUCCESS (status)) + { + nbytes_now = io.Information; + ptr = ((char *) ptr) + nbytes_now; + nbytes += nbytes_now; + /* 0 bytes returned? EAGAIN. See above. */ + if (nbytes == 0) + set_errno (EAGAIN); + } + else if (STATUS_PIPE_IS_CLOSED (status)) + { + set_errno (EPIPE); + raise (SIGPIPE); + } + else + __seterrno_from_nt_status (status); + + if (nbytes_now == 0) + break; + } + if (evt) + CloseHandle (evt); + if (status == STATUS_THREAD_SIGNALED && nbytes == 0) + set_errno (EINTR); + else if (status == STATUS_THREAD_CANCELED) + pthread::static_cancel_self (); + return nbytes ?: -1; +} + int fhandler_base::get_default_fmode (int flags) { @@ -1464,6 +1587,7 @@ fhandler_base::fhandler_base () : _refcnt (0), openflags (0), unique_id (0), + max_atomic_write (DEFAULT_PIPEBUFSIZE), archetype (NULL), usecount (0) { diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 032ab5fb0..ebddcca88 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -218,6 +218,9 @@ class fhandler_base HANDLE read_state; + /* Used by fhandler_pipe and fhandler_fifo. */ + size_t max_atomic_write; + public: LONG inc_refcnt () {return InterlockedIncrement (&_refcnt);} LONG dec_refcnt () {return InterlockedDecrement (&_refcnt);} @@ -453,6 +456,7 @@ public: virtual void __reg3 raw_read (void *ptr, size_t& ulen); virtual ssize_t __reg3 raw_write (const void *ptr, size_t ulen); + ssize_t __reg3 raw_write_pipe_fifo (const void *ptr, size_t ulen); /* Virtual accessor functions to hide the fact that some fd's have two handles. */ @@ -1173,7 +1177,6 @@ class fhandler_pipe: public fhandler_base private: HANDLE read_mtx; pid_t popen_pid; - size_t max_atomic_write; void set_pipe_non_blocking (bool nonblocking); public: fhandler_pipe (); @@ -1342,7 +1345,6 @@ class fhandler_fifo: public fhandler_base int nhandlers; /* Number of elements in the array. */ af_unix_spinlock_t _fifo_client_lock; bool reader, writer, duplexer; - size_t max_atomic_write; fifo_reader_id_t me; HANDLE shmem_handle; diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index b55ba95e7..11b06ed08 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -108,14 +108,6 @@ */ -/* This is only to be used for writers. When reading, -STATUS_PIPE_EMPTY simply means there's no data to be read. */ -#define STATUS_PIPE_IS_CLOSED(status) \ - ({ NTSTATUS _s = (status); \ - _s == STATUS_PIPE_CLOSING \ - || _s == STATUS_PIPE_BROKEN \ - || _s == STATUS_PIPE_EMPTY; }) - #define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \ ({ NTSTATUS _s = (status); \ _s == STATUS_INSTANCE_NOT_AVAILABLE \ @@ -134,7 +126,6 @@ fhandler_fifo::fhandler_fifo (): cancel_evt (NULL), thr_sync_evt (NULL), pipe_name_buf (NULL), fc_handler (NULL), shandlers (0), nhandlers (0), reader (false), writer (false), duplexer (false), - max_atomic_write (DEFAULT_PIPEBUFSIZE), me (null_fr_id), shmem_handle (NULL), shmem (NULL), shared_fc_hdl (NULL), shared_fc_handler (NULL) { @@ -1141,94 +1132,7 @@ fhandler_fifo::wait (HANDLE h) ssize_t __reg3 fhandler_fifo::raw_write (const void *ptr, size_t len) { - ssize_t ret = -1; - size_t nbytes = 0; - ULONG chunk; - NTSTATUS status = STATUS_SUCCESS; - IO_STATUS_BLOCK io; - HANDLE evt = NULL; - - if (!len) - return 0; - - if (len <= max_atomic_write) - chunk = len; - else if (is_nonblocking ()) - chunk = len = max_atomic_write; - else - chunk = max_atomic_write; - - /* Create a wait event if the FIFO is in blocking mode. */ - if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL))) - { - __seterrno (); - return -1; - } - - /* Write in chunks, accumulating a total. If there's an error, just - return the accumulated total unless the first write fails, in - which case return -1. */ - while (nbytes < len) - { - ULONG_PTR nbytes_now = 0; - size_t left = len - nbytes; - ULONG len1; - DWORD waitret = WAIT_OBJECT_0; - - if (left > chunk) - len1 = chunk; - else - len1 = (ULONG) left; - nbytes_now = 0; - status = NtWriteFile (get_handle (), evt, NULL, NULL, &io, - (PVOID) ptr, len1, NULL, NULL); - if (evt && status == STATUS_PENDING) - { - waitret = cygwait (evt); - if (waitret == WAIT_OBJECT_0) - status = io.Status; - } - if (waitret == WAIT_CANCELED) - status = STATUS_THREAD_CANCELED; - else if (waitret == WAIT_SIGNALED) - status = STATUS_THREAD_SIGNALED; - else if (isclosed ()) /* A signal handler might have closed the fd. */ - { - if (waitret == WAIT_OBJECT_0) - set_errno (EBADF); - else - __seterrno (); - } - else if (NT_SUCCESS (status)) - { - nbytes_now = io.Information; - /* NtWriteFile returns success with # of bytes written == 0 - if writing on a non-blocking pipe fails because the pipe - buffer doesn't have sufficient space. */ - if (nbytes_now == 0) - set_errno (EAGAIN); - ptr = ((char *) ptr) + chunk; - nbytes += nbytes_now; - } - else if (STATUS_PIPE_IS_CLOSED (status)) - { - set_errno (EPIPE); - raise (SIGPIPE); - } - else - __seterrno_from_nt_status (status); - if (nbytes_now == 0) - len = 0; /* Terminate loop. */ - if (nbytes > 0) - ret = nbytes; - } - if (evt) - NtClose (evt); - if (status == STATUS_THREAD_SIGNALED && ret < 0) - set_errno (EINTR); - else if (status == STATUS_THREAD_CANCELED) - pthread::static_cancel_self (); - return ret; + return fhandler_base::raw_write_pipe_fifo (ptr, len); } /* Called from raw_read and select.cc:peek_fifo. */ diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc index 81b1aed5e..88c98d41b 100644 --- a/winsup/cygwin/fhandler_pipe.cc +++ b/winsup/cygwin/fhandler_pipe.cc @@ -20,18 +20,9 @@ details. */ #include "pinfo.h" #include "shared_info.h" -/* This is only to be used for writing. When reading, -STATUS_PIPE_EMPTY simply means there's no data to be read. */ -#define STATUS_PIPE_IS_CLOSED(status) \ - ({ NTSTATUS _s = (status); \ - _s == STATUS_PIPE_CLOSING \ - || _s == STATUS_PIPE_BROKEN \ - || _s == STATUS_PIPE_EMPTY; }) - fhandler_pipe::fhandler_pipe () : fhandler_base (), popen_pid (0) { - max_atomic_write = DEFAULT_PIPEBUFSIZE; need_fork_fixup (true); } @@ -342,117 +333,7 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) ssize_t __reg3 fhandler_pipe::raw_write (const void *ptr, size_t len) { - size_t nbytes = 0; - ULONG chunk; - NTSTATUS status = STATUS_SUCCESS; - IO_STATUS_BLOCK io; - HANDLE evt = NULL; - - if (!len) - return 0; - - if (len <= max_atomic_write) - chunk = len; - else if (is_nonblocking ()) - chunk = len = max_atomic_write; - else - chunk = max_atomic_write; - - /* Create a wait event if the pipe is in blocking mode. */ - if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL))) - { - __seterrno (); - return -1; - } - - /* Write in chunks, accumulating a total. If there's an error, just - return the accumulated total unless the first write fails, in - which case return -1. */ - while (nbytes < len) - { - ULONG_PTR nbytes_now = 0; - size_t left = len - nbytes; - ULONG len1; - DWORD waitret = WAIT_OBJECT_0; - - if (left > chunk) - len1 = chunk; - else - len1 = (ULONG) left; - /* NtWriteFile returns success with # of bytes written == 0 if writing - on a non-blocking pipe fails because the pipe buffer doesn't have - sufficient space. - - POSIX requires - - A write request for {PIPE_BUF} or fewer bytes shall have the - following effect: if there is sufficient space available in the - pipe, write() shall transfer all the data and return the number - of bytes requested. Otherwise, write() shall transfer no data and - return -1 with errno set to [EAGAIN]. - - - A write request for more than {PIPE_BUF} bytes shall cause one - of the following: - - - When at least one byte can be written, transfer what it can and - return the number of bytes written. When all data previously - written to the pipe is read, it shall transfer at least {PIPE_BUF} - bytes. - - - When no data can be written, transfer no data, and return -1 with - errno set to [EAGAIN]. */ - while (len1 > 0) - { - status = NtWriteFile (get_handle (), evt, NULL, NULL, &io, - (PVOID) ptr, len1, NULL, NULL); - if (evt || !NT_SUCCESS (status) || io.Information > 0 - || len <= PIPE_BUF) - break; - len1 >>= 1; - } - if (evt && status == STATUS_PENDING) - { - waitret = cygwait (evt); - if (waitret == WAIT_OBJECT_0) - status = io.Status; - } - if (waitret == WAIT_CANCELED) - status = STATUS_THREAD_CANCELED; - else if (waitret == WAIT_SIGNALED) - status = STATUS_THREAD_SIGNALED; - else if (isclosed ()) /* A signal handler might have closed the fd. */ - { - if (waitret == WAIT_OBJECT_0) - set_errno (EBADF); - else - __seterrno (); - } - else if (NT_SUCCESS (status)) - { - nbytes_now = io.Information; - ptr = ((char *) ptr) + nbytes_now; - nbytes += nbytes_now; - /* 0 bytes returned? EAGAIN. See above. */ - if (nbytes == 0) - set_errno (EAGAIN); - } - else if (STATUS_PIPE_IS_CLOSED (status)) - { - set_errno (EPIPE); - raise (SIGPIPE); - } - else - __seterrno_from_nt_status (status); - - if (nbytes_now == 0) - break; - } - if (evt) - CloseHandle (evt); - if (status == STATUS_THREAD_SIGNALED && nbytes == 0) - set_errno (EINTR); - else if (status == STATUS_THREAD_CANCELED) - pthread::static_cancel_self (); - return nbytes ?: -1; + return fhandler_base::raw_write_pipe_fifo (ptr, len); } void -- 2.33.0 --------------CE8C8377AFA9E856C5F6F72E--