---
name: "gensio_set_sync"
section: "3"
platform: "linux"
package: "gensio"
version: "3.0.4-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/gensio_set_sync"
---

# gensio\_set\_sync(3)

Synchronous I/O operations on a gensio

## NAME

gensio\_set\_sync, gensio\_clear\_sync, gensio\_read\_s, gensio\_write\_s - Synchronous I/O operations on a gensio

## SYNOPSIS

**#include \<gensio/gensio.h\>**

- **int gensio\_set\_sync(struct gensio \*io);**

  - **int gensio\_clear\_sync(struct gensio \*io);**

  - **int gensio\_read\_s(struct gensio \*io, gensiods \*count,**

  **void \*data, gensiods datalen,**\
   **struct gensio\_time \*timeout);**

- **int gensio\_read\_s\_intr(struct gensio \*io, gensiods \*count,**

  **void \*data, gensiods datalen,**\
   **struct gensio\_time \*timeout);**

- **int gensio\_write\_s(struct gensio \*io, gensiods \*count,**

  **const void \*data, gensiods datalen,**\
   **struct gensio\_time \*timeout);**

- **int gensio\_write\_s\_intr(struct gensio \*io, gensiods \*count,**

  **const void \*data, gensiods datalen,**\
   **struct gensio\_time \*timeout);**

## DESCRIPTION

Normal gensio operation is asynchronous callback based.  This serves most programs fairly well, especially if they are listening to multiple connections at the same time.  You wouldn't want to write a compiler this way, but if you are writing something that is driven by external events, this event-driven type of programming works well.  If you think about it, if you are using something like poll, select, etc., you almost always end up with something like:

-

  poll(fds...)\
   if (fd1 read is set)\
  \
      call fd1\_read\_handler()\
   if (fd1 write is set)\
  \
      call fd1\_write\_handler()\
   if (fd2 read is set)\
      ...

The gensio handling does all this for you.  Just register a handler with the gensio to get the read and write calls.  It's more efficient, neater, and you end up with less code.

But occasionally you need to do something synchronous with the program execution.  For instance, in gtlsshd, if the initial certificate and password verification fails, it uses PAM to handle reading the password from the remote gensio.  This requires synchronous I/O, and it uses this capability.

**gensio\_set\_sync** sets up the gensio for synchronous I/O.  If you do this, the event callback that is currently registered will no longer receive read and write callbacks.  It \*will\* receive other callbacks.  You must call this before doing any of the synchronous read and write operations. This function will block (while handling normal gensio events) until no callbacks are active.

**gensio\_clear\_sync** returns the gensio to asynchronous I/O.  The callback will be restored to the one that was set when gensio\_set\_sync() was called.

**gensio\_read\_s** Waits for data from the gensio, up to *datalen* bytes. *count* (if not NULL) will be updated to the actual number of bytes read. This will wait for any read and will return whatever that read was, even if it is less than *datalen.* This function waits for the amount of time in *timeout.* *timeout* is updated to the amount of time left to wait.  If *timeout* is NULL, wait forever.

**gensio\_write\_s** writes data to the gensio. *count* (if not NULL) will be updated to the actual number of bytes written. This function will wait until either the timeout occurs or all the data is written. This function waits for the amount of time in *timeout.* *timeout* is updated to the amount of time left to wait.  If *timeout* is NULL, wait forever.

**gensio\_read\_s\_intr** and **gensio\_write\_s\_intr** are like **gensio\_read\_s** and **gensio\_write\_s,** but they return immediately if an signal interrupt occurs.  On systems without signals, these are the same as **gensio\_read\_s** and **gensio\_write\_s.**

## RETURN VALUES

Zero is returned on success, or a gensio error on failure.

## SEE ALSO

[gensio\_err(3)](/gensio_err/3.md), [gensio(5)](/gensio/5.md)
