Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUMM-506 Prevent malforming payload due to I/O exception #133

Merged

Conversation

ncreated
Copy link
Member

@ncreated ncreated commented Jun 12, 2020

What and why?

🐛 Some payloads send from SDK were malformed.

The reason was not performing writes atomically:

// pseudo-code

let separatorData = ",".utf8Data
try writer.write(separatorData)
try writer.write(logData)

In rare cases, when the I/O exception was thrown for the second write, it was leaving the file's content malformed.

How?

The fix is to perform atomic writes:

// pseudo-code

let logWithSeparatorData = ",".utf8Data + logData
try writer.write(logWithSeparatorData)

The red unit test for payload malformation was added, then it was made green with a fix.

Later improvements

The File interface is not resistant for this sort of bugs, as it doesn't perform transactional write even if it looks like:

// FileTests.swift

try file.append { write in
    try write(Data([0x42, 0x42, 0x42, 0x42, 0x42])) // 5 bytes
    try write(Data([0x41, 0x41, 0x41, 0x41, 0x41])) // 5 bytes
}

As this requires additional refactoring, to not impact the hotfix scope, I will open a separate PR changing the WritableFile interface from:

func append(transaction: ((Data) throws -> Void) throws -> Void) throws

to simply:

func append(data Data) throws

Review checklist

  • Feature or bugfix MUST have appropriate tests (unit, integration)
  • Make sure each commit and the PR mention the Issue number or JIRA reference

@ncreated ncreated self-assigned this Jun 12, 2020
@ncreated ncreated marked this pull request as ready for review June 12, 2020 11:24
@ncreated ncreated requested a review from a team as a code owner June 12, 2020 11:24
@buranmert buranmert added this to the 1.2.2 milestone Jun 12, 2020
@buranmert
Copy link
Contributor

@ncreated i just noticed that in some cases the log has \u0000 instead of extra ,.
i guess that's because the second try write(data) throws and leaves \u0000 there, can this be true?
if so, how can we make sure that we don't leave corrupt chars in the file?

@buranmert
Copy link
Contributor

note: we still can't figure out why \u0000 appears, we couldn't reproduce it and it seems very rare (possibly a few in a million logs)

we will ship this hotfix version and keep monitoring the issue

@ncreated
Copy link
Member Author

I added the test to prevent also malformations in the middle of the file: 792c74c This is to additionally check if the 0x00 byte is not inserted.

@ncreated ncreated requested a review from buranmert June 12, 2020 13:15
@buranmert
Copy link
Contributor

buranmert commented Jun 12, 2020

i suspect that when FileHandler.write(data) raises a certain kind of exception, it somehow changes offsetInFile without adding non-null bytes.

can we add something like this?

func append(transaction: ((Data) throws -> Void) throws -> Void) throws {
  let fileHandle = try FileHandle(forWritingTo: url)

  var errorThrown = true
  let initialOffset = fileHandle.offsetInFile
  defer {
    let finalOffset = fileHandle.offsetInFile
    if errorThrown && (initialOffset != finalOffset) {
      fileHandle.moveTheEndOfFile(to: initialOffset) // this should fix it but i don't know how we can do this safely
    }
    fileHandle.closeFile()
  }
  ...
  errorThrown = false
}       

EDIT: snippet changed to a potential fix from monitoring the issue

@ncreated
Copy link
Member Author

can we add something like this?

@buranmert even if it works, this does neither fix the problem nor empower us with reporting. I think it's better to iterate on this issue and first see if we'll be receiving malformed logs after applying this hotfix. WDYT?

@buranmert
Copy link
Contributor

yes, fixing null char issue doesn't seem trivial; let's go with this hotfix and keep monitoring 👍

@ncreated ncreated merged commit 6b199e1 into master Jun 12, 2020
@ncreated ncreated deleted the ncreated/RUMM-506-prevent-malforming-payload-on-io-exceptions branch June 12, 2020 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants