carb::launcher::OnProcessReadFn

Defined in carb/launcher/ILauncher.h

using carb::launcher::OnProcessReadFn = void (*)(const void *data, size_t bytes, void *context)

Prototype for a stream read callback function.

Remark

This callback will be performed any time data is successfully read from one of the child process’s output streams (ie: stdout or stderr). The call will be performed on a worker thread that was created specifically for the child process. This callback will be performed as soon after reading the data as possible. The reader thread will remain in an efficient wait state while there is no data read to be read. It is the callback’s responsibility to ensure any shared resources that are accessed in the callback are appropriately protected from race conditions and general thread safety issues.

Remark

When reading from one of the child process’ output streams, every effort will be taken to ensure the contents of at least one ‘message’ is delivered to the callback at a time. A message can be thought of as the unit of data that was last written to the stream on the child process’s side - for example, the output of a single call to fwrite() or fprintf(). However, there are a some caveats to this behavior that the callback and its owner need to be able to handle:

  • It is possible that depending on the size and arrival times of messages, multiple messages may be concatenated into a single callback call. The callback needs to be able to handle this by being able to identify expected message ends and properly parse them out if needed.

  • If the current message or set of messages fills up the read buffer, the buffer as it is will be delivered to the callback with the last message truncated. The remainder of the message will be sent in the next callback. The callback needs to be able to handle this by either using a buffer size appropriate for the expected output of the child process, or by having the callback simply concatenate incoming data onto a data queue that is then processed elsewhere.

Remark

This callback should attempt to complete its task as quickly as possible to avoid blocking the read thread. If the callback blocks or takes a long time to process it may result in blocking the child process’s attempts to write to the stream. The child process’ thread will be effectively stopped until buffer space is freed up on the parent’s read side. It is best practice to have the callback simply queue up new data for later consumption on another thread in the parent process or to do a few simple string or data checks if searching for a specific incoming data message.

Remark

When the stream for this callback ends due to either the child or parent process closing it, one final callback will be performed. The last callback will always have a bytes value of 0 in this case. All other callbacks during the stream will have a non-zero bytes value. Even in this final callback case however, a non-nullptr data buffer will still be provided. Once the zero sized buffer has been delivered, the parent process can safely assume that the child process is done transmitting any data to the parent.

Param data

[in] The buffer of data that was read from the child process’s stream. This will never be nullptr. Only the first bytes bytes of data in this buffer will contain valid data. Any data beyond that should be considered undefined and not accessed.

Param bytes

[in] The number of bytes of valid data in the data buffer. This will never be 0 as long as the connection to the child process is active. When the child process exits and the read thread has read all of the data from the child process, one final callback will be performed passing 0 for the byte count to indicate the end of the stream. This count will not exceed the buffer size specified in the original call to ILauncher::openProcess().

Param context

[in] The context value that was originally passed to ILauncher::openProcess() when the child process was created.

Return

No return value.