If buffer lists with too many buffers would be written before, a stack
overflow would happen because of memory linear with the number of
GstMemory would be allocated on the stack. This could happen for example
when filesink is configured with a very big buffer size.
Instead now move the buffer and buffer list writing into the helper
functions and at most write IOV_MAX memories at once. Anything bigger
than that wouldn't be passed to writev() anyway and written differently
in the previous code, so this also potentially speeds up writing for
these cases.
For example the following pipeline would crash with a stackoverflow:
gst-launch-1.0 audiotestsrc ! filesink buffer-size=1073741824 location=/dev/null
According to [1] EINTR is a possible errno for fsync() and it happens in
reality on linux (video writing via splitmuxsink with robust muxing enabled
on a cifs mounted network share), so handle it as all other EINTR
(do/while(errno == EINTR)).
Fixes:
GError.message: Error while writing to file "vidoe_001.mp4". GError.domain: 2372 GError.code: 10 from: FileSink debug: gstfilesink.c(849): gst_file_sink_render (): /GstPipeline:Pipeline/GstSplitMuxSink:SplitMuxSink/GstBin:QueueBin/GstFileSink:FileSink: Interrupted system call
Signed-off-by: Peter Seiderer <ps.report@gmx.net>
This seems to happen when another client is accessing the file at the
same time, and retrying after a short amount of time solves it.
Sometimes partial data is written at that point already but we have no
idea how much it is, or if what was written is correct (it sometimes
isn't) so we always first seek back to the current position and repeat
the whole failed write.
It happens at least on Linux and macOS on SMB/CIFS and NFS file systems.
Between write attempts that failed with EACCES we wait 10ms, and after
enough consecutive tries that failed with EACCES we simply time out.
In theory a valid EACCES for files to which we simply have no access
should've happened already during the call to open(), except for NFS
(see open(2)).
This can be enabled with the new max-transient-error-timeout property, and
a new o-sync boolean property was added to open the file in O_SYNC mode
as without that it's not guaranteed that we get EACCES for the actual
writev() call that failed but might only get it at a later time.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/305
Otherwise we write out the SYNC_AFTER buffer immediately, and the
previously queued up buffers afterwards which then breaks the order of
data.
Also add various debug output.
fflush() has no effect because we use writev() directly, so fsync()
should be used instead which is actually flushing the kernel-side
buffers.
As a next step, a non-line-buffered buffering mode is to be added.
https://bugzilla.gnome.org/show_bug.cgi?id=794173
The correct behaviour of anything stuck in the ->render() function
between ->unlock() and ->unlock_stop() is to call
gst_base_sink_wait_preroll() and only return an error if this returns an
error, otherwise, it must continue where it left off!
https://bugzilla.gnome.org/show_bug.cgi?id=773912
Sometimes filesink cleanup during stop may fail due to fclose error.
In this case object left partial cleanup with no file opened
but still holding old file descriptor.
It's not possible to change location property in a such state,
so next start will cause old file overwrite if 'append' does not set.
According to man page and POSIX standard about fclose behavior(extract):
------------------------------------------------------------------------
The fclose() function shall cause the stream pointed to by stream
to be flushed and the associated file to be closed.
...
Whether or not the call succeeds, the stream shall be disassociated
from the file and any buffer set by the setbuf() or setvbuf()
function shall be disassociated from the stream.
...
The fclose() function shall perform the equivalent of a close()
on the file descriptor that is associated with the stream
pointed to by stream.
After the call to fclose(), any use of stream results
in undefined behavior.
------------------------------------------------------------------------
So file is in 'closed' state no matter if fclose succeed or not.
And cleanup could be continued.
https://bugzilla.gnome.org/show_bug.cgi?id=757596
Add new wait_eos vmethod to wait for the eos timeout before posting the EOS
message on the bus.
Add default event handler. Move the default event actions in there. Call the
event vmethod from the pad event handler. Subclasses are now supposed to chain
up to the parent event handler or unref the event and do their own thing.
Avoid passing unused parameters to functions.
Add a vmethod to handle the pad query.
Install a default handler for the pad query.
Add a vmethod to setup the allocation properties.
Use the new query function in filesink
This reverts commit cf4fbc005c.
This change did not improve the situation for bindings because
queries are usually created, then directly passed to a function
and not stored elsewhere, and the writability problem with
miniobjects usually happens with buffers or caps instead.
Improve GstSegment, rename some fields. The idea is to have the GstSegment
structure represent the timing structure of the buffers as they are generated by
the source or demuxer element.
gst_segment_set_seek() -> gst_segment_do_seek()
Rename the NEWSEGMENT event to SEGMENT.
Make parsing of the SEGMENT event into a GstSegment structure.
Pass a GstSegment structure when making a new SEGMENT event. This allows us to
pass the timing info directly to the next element. No accumulation is needed in
the receiving element, all the info is inside the element.
Remove gst_segment_set_newsegment(): This function as used to accumulate
segments received from upstream, which is now not needed anymore because the
segment event contains the complete timing information.
Passing e.g. location=foo would lead to warnings because g_filename_to_uri()
wants an absolute file path and returns NULL otherwise. Use brand-new
gst_filename_to_uri() instead, which will try harder to create a proper
URI for us.
Also add unit test.