Skip to content

Commit

Permalink
correctly handle empty files on upload
Browse files Browse the repository at this point in the history
  • Loading branch information
tolk-vm committed Jan 26, 2023
1 parent 10c649f commit 4160dc1
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 10 deletions.
11 changes: 7 additions & 4 deletions internal/client/files-uploading.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,17 @@ func uploadFileByChunks(stream pb.CompilationService_UploadFileStreamClient, chu
defer fd.Close()

var n int
var sentChunks = 0 // used to correctly handle empty files (when Read returns EOF immediately)
for {
n, err = fd.Read(chunkBuf)
if err == io.EOF {
break
}
if err != nil {
if err != nil && err != io.EOF {
return err
}
if err == io.EOF && sentChunks != 0 {
break
}
sentChunks++

err = stream.Send(&pb.UploadFileChunkRequest{
ClientID: clientID,
SessionID: sessionID,
Expand Down
16 changes: 11 additions & 5 deletions internal/client/invocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ type Invocation struct {
cxxIDirs IncludeDirs // -I / -iquote / -isystem go here
depsFlags DepCmdFlags // -MD -MF file and others, used for .d files generation (not passed to server)

doneState int32 // see Invocation.DoneRecvObj
wgUpload sync.WaitGroup
wgRecv sync.WaitGroup
waitUploads int32 // files still waiting for upload to finish; 0 releases wgUpload; see Invocation.DoneUploadFile
doneRecv int32 // 1 if o file received or failed receiving; 1 releases wgRecv; see Invocation.DoneRecvObj
wgUpload sync.WaitGroup
wgRecv sync.WaitGroup

// when remote compilation starts, the server starts a server.Session (with the same sessionID)
// after it finishes, we have these fields filled (and objOutFile saved)
Expand Down Expand Up @@ -232,7 +233,7 @@ func (invocation *Invocation) CollectDependentIncludes(disableOwnIncludes bool)
}

func (invocation *Invocation) DoneRecvObj(err error) {
if atomic.SwapInt32(&invocation.doneState, 1) == 0 {
if atomic.SwapInt32(&invocation.doneRecv, 1) == 0 {
if err != nil {
invocation.err = err
}
Expand All @@ -244,11 +245,16 @@ func (invocation *Invocation) DoneUploadFile(err error) {
if err != nil {
invocation.err = err
}
atomic.AddInt32(&invocation.waitUploads, -1)
invocation.wgUpload.Done() // will end up after all required files uploaded/failed
}

func (invocation *Invocation) ForceInterrupt(err error) {
// hopefully, an invocation can't hang on uploading files, it could hang only on waiting for obj
logClient.Error("force interrupt", "sessionID", invocation.sessionID, invocation.cppInFile, err)
// release invocation.wgUpload
for atomic.LoadInt32(&invocation.waitUploads) != 0 {
invocation.DoneUploadFile(err)
}
// release invocation.wgDone
invocation.DoneRecvObj(err)
}
3 changes: 2 additions & 1 deletion internal/client/remote-connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ func (remote *RemoteConnection) StartCompilationSession(invocation *Invocation,

// UploadFilesToRemote uploads files to the remote in parallel and finishes after all of them are done.
func (remote *RemoteConnection) UploadFilesToRemote(invocation *Invocation, requiredFiles []*pb.FileMetadata, fileIndexesToUpload []uint32) error {
invocation.wgUpload.Add(len(fileIndexesToUpload))
invocation.waitUploads = int32(len(fileIndexesToUpload))
invocation.wgUpload.Add(int(invocation.waitUploads))

for _, fileIndex := range fileIndexesToUpload {
remote.filesUploading.StartUploadingFileToRemote(invocation, requiredFiles[fileIndex], fileIndex)
Expand Down
Empty file added tests/dt/cmake1/src/empty.h
Empty file.
1 change: 1 addition & 0 deletions tests/dt/cmake1/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// main.cpp
#include "all-headers.h"
#include "empty.h"

int main() {
std::cout << sum(1, 2) << std::endl;
Expand Down

0 comments on commit 4160dc1

Please sign in to comment.