xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/eintr.h (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
18dffb485Schristos /* Utility for handling interrupted syscalls by signals.
28dffb485Schristos 
3*5ba1f45fSchristos    Copyright (C) 2020-2024 Free Software Foundation, Inc.
48dffb485Schristos 
58dffb485Schristos    This file is part of GDB.
68dffb485Schristos 
78dffb485Schristos    This program is free software; you can redistribute it and/or modify
88dffb485Schristos    it under the terms of the GNU General Public License as published by
98dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
108dffb485Schristos    (at your option) any later version.
118dffb485Schristos 
128dffb485Schristos    This program is distributed in the hope that it will be useful,
138dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
148dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158dffb485Schristos    GNU General Public License for more details.
168dffb485Schristos 
178dffb485Schristos    You should have received a copy of the GNU General Public License
188dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #ifndef GDBSUPPORT_EINTR_H
218dffb485Schristos #define GDBSUPPORT_EINTR_H
228dffb485Schristos 
238dffb485Schristos #include <cerrno>
248dffb485Schristos 
258dffb485Schristos namespace gdb
268dffb485Schristos {
278dffb485Schristos /* Repeat a system call interrupted with a signal.
288dffb485Schristos 
298dffb485Schristos    A utility for handling interrupted syscalls, which return with error
308dffb485Schristos    and set the errno to EINTR.  The interrupted syscalls can be repeated,
318dffb485Schristos    until successful completion.  This utility avoids wrapping code with
328dffb485Schristos    manual checks for such errors which are highly repetitive.
338dffb485Schristos 
348dffb485Schristos    For example, with:
358dffb485Schristos 
368dffb485Schristos    ssize_t ret;
378dffb485Schristos    do
388dffb485Schristos      {
398dffb485Schristos        errno = 0;
408dffb485Schristos        ret = ::write (pipe[1], "+", 1);
418dffb485Schristos      }
428dffb485Schristos    while (ret == -1 && errno == EINTR);
438dffb485Schristos 
448dffb485Schristos    You could wrap it by writing the wrapped form:
458dffb485Schristos 
464b169a6bSchristos    ssize_t ret = gdb::handle_eintr (-1, ::write, pipe[1], "+", 1);
478dffb485Schristos 
484b169a6bSchristos    ERRVAL specifies the failure value indicating that the call to the
494b169a6bSchristos    F function with ARGS... arguments was possibly interrupted with a
504b169a6bSchristos    signal.  */
518dffb485Schristos 
524b169a6bSchristos template<typename ErrorValType, typename Fun, typename... Args>
534b169a6bSchristos inline auto
544b169a6bSchristos handle_eintr (ErrorValType errval, const Fun &f, const Args &... args)
554b169a6bSchristos   -> decltype (f (args...))
568dffb485Schristos {
574b169a6bSchristos   decltype (f (args...)) ret;
584b169a6bSchristos 
598dffb485Schristos   do
608dffb485Schristos     {
618dffb485Schristos       errno = 0;
624b169a6bSchristos       ret = f (args...);
638dffb485Schristos     }
644b169a6bSchristos   while (ret == errval && errno == EINTR);
654b169a6bSchristos 
668dffb485Schristos   return ret;
678dffb485Schristos }
684b169a6bSchristos 
694b169a6bSchristos } /* namespace gdb */
708dffb485Schristos 
718dffb485Schristos #endif /* GDBSUPPORT_EINTR_H */
72