Skip to content

Commit 6000bb6

Browse files
authored
Merge pull request #1133 from NativeScript/trifonov/v8-lock
Lock files for reading when they are being replaced
2 parents a09d51a + b13da90 commit 6000bb6

File tree

8 files changed

+77
-12
lines changed

8 files changed

+77
-12
lines changed

test-app/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,14 @@ private void createOrOverrideFile(String fileName, byte[] content) throws IOExce
356356

357357
fileToCreate.getParentFile().mkdirs();
358358
FileOutputStream fos = new FileOutputStream(fileToCreate.getCanonicalPath());
359+
runtime.lock();
359360
fos.write(content);
360361
fos.close();
361362

362363
} catch (Exception e) {
363364
throw new IOException(String.format("\nLiveSync: failed to write file: %s\nOriginal Exception: %s", fileName, e.toString()));
365+
} finally {
366+
runtime.unlock();
364367
}
365368
}
366369

test-app/app/src/main/java/com/tns/RuntimeHelper.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,18 @@ public static Runtime initRuntime(Application app) {
192192

193193
// if app is in debuggable mode run livesync service
194194
// runtime needs to be initialized before the NativeScriptSyncService is enabled because it uses runtime.runScript(...)
195-
// initLiveSync(runtime, logger, app);
195+
initLiveSync(runtime, logger, app);
196+
197+
// CLI will create this file when initial sync is needed and then will remove it after syncing the fails and restarting the app
198+
File liveSyncFile = new File("/data/local/tmp/" + app.getPackageName() + "-livesync-in-progress");
199+
if(liveSyncFile.exists()) {
200+
try {
201+
// wait for the livesync to complete
202+
Thread.sleep(30000);
203+
} catch (Exception ex) {
204+
205+
}
206+
}
196207
}
197208

198209
runtime.runScript(new File(appDir, "internal/ts_helpers.js"));

test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Generator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,9 @@ private void writeMethodBody(Method m, boolean isConstructor, boolean isApplicat
655655
}
656656

657657
// call liveSync initialization
658-
if (m.getName().equals("onCreate") && isActivityClass) {
659-
w.writeln("\t\tcom.tns.RuntimeHelper.initLiveSync(this.getApplication());");
660-
}
658+
// if (m.getName().equals("onCreate") && isActivityClass) {
659+
// w.writeln("\t\tcom.tns.RuntimeHelper.initLiveSync(this.getApplication());");
660+
// }
661661
}
662662

663663
private void writeType(Type t, Writer w) {

test-app/runtime/src/main/cpp/ModuleInternal.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#include "include/v8.h"
1818
#include "CallbackHandlers.h"
1919
#include "ManualInstrumentation.h"
20+
#include "Runtime.h"
2021
#include <sstream>
22+
#include <mutex>
2123
#include <libgen.h>
2224
#include <dlfcn.h>
2325

@@ -397,7 +399,7 @@ Local<Object> ModuleInternal::LoadData(Isolate* isolate, const string& path) {
397399
tns::instrumentation::Frame frame(frameName.c_str());
398400
Local<Object> json;
399401

400-
auto jsonData = File::ReadText(path);
402+
auto jsonData = Runtime::GetRuntime(m_isolate)->ReadFileText(path);
401403

402404
TryCatch tc(isolate);
403405

@@ -428,9 +430,8 @@ Local<Object> ModuleInternal::LoadData(Isolate* isolate, const string& path) {
428430

429431
Local<String> ModuleInternal::WrapModuleContent(const string& path) {
430432
TNSPERF();
431-
string content = File::ReadText(path);
432433

433-
auto separatorIndex = path.find_last_of("/");
434+
string content = Runtime::GetRuntime(m_isolate)->ReadFileText(path);
434435

435436
// TODO: Use statically allocated buffer for better performance
436437
string result(MODULE_PROLOGUE);

test-app/runtime/src/main/cpp/Runtime.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "include/zipconf.h"
2323
#include <csignal>
2424
#include <sstream>
25+
#include <mutex>
2526
#include <dlfcn.h>
2627
#include <console/Console.h>
2728
#include "NetworkDomainCallbackHandlers.h"
@@ -188,6 +189,26 @@ void Runtime::Init(jstring filesPath, jstring nativeLibDir, bool verboseLoggingE
188189
s_isolate2RuntimesCache.insert(make_pair(m_isolate, this));
189190
}
190191

192+
std::string Runtime::ReadFileText(const std::string& filePath) {
193+
#ifdef APPLICATION_IN_DEBUG
194+
std::lock_guard<std::mutex> lock(m_fileWriteMutex);
195+
#endif
196+
return File::ReadText(filePath);
197+
}
198+
199+
200+
void Runtime::Lock() {
201+
#ifdef APPLICATION_IN_DEBUG
202+
m_fileWriteMutex.lock();
203+
#endif
204+
}
205+
206+
void Runtime::Unlock() {
207+
#ifdef APPLICATION_IN_DEBUG
208+
m_fileWriteMutex.unlock();
209+
#endif
210+
}
211+
191212
void Runtime::RunModule(JNIEnv* _env, jobject obj, jstring scriptFile) {
192213
JEnv env(_env);
193214

@@ -209,7 +230,8 @@ jobject Runtime::RunScript(JNIEnv* _env, jobject obj, jstring scriptFile) {
209230
auto context = isolate->GetCurrentContext();
210231

211232
auto filename = ArgConverter::jstringToString(scriptFile);
212-
auto src = File::ReadText(filename);
233+
auto src = ReadFileText(filename);
234+
213235
auto source = ArgConverter::ConvertToV8String(isolate, src);
214236

215237
TryCatch tc(isolate);
@@ -476,7 +498,7 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
476498

477499
// check for custom script to include in the snapshot
478500
if (Constants::V8_HEAP_SNAPSHOT_SCRIPT.size() > 0 && File::Exists(Constants::V8_HEAP_SNAPSHOT_SCRIPT)) {
479-
customScript = File::ReadText(Constants::V8_HEAP_SNAPSHOT_SCRIPT);
501+
customScript = ReadFileText(Constants::V8_HEAP_SNAPSHOT_SCRIPT);
480502
}
481503

482504
DEBUG_WRITE_FORCE("Creating heap snapshot");

test-app/runtime/src/main/cpp/Runtime.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Profiler.h"
1111
#include "ModuleInternal.h"
1212
#include "File.h"
13+
#include <mutex>
1314

1415
jobject ConvertJsValueToJavaObject(tns::JEnv& env, const v8::Local<v8::Value>& value, int classReturnType);
1516

@@ -56,8 +57,13 @@ class Runtime {
5657
void ClearStartupData(JNIEnv* env, jobject obj);
5758
void DestroyRuntime();
5859

60+
void Lock();
61+
void Unlock();
62+
5963
static v8::Platform* platform;
6064

65+
std::string ReadFileText(const std::string& filePath);
66+
6167
private:
6268
Runtime(JNIEnv* env, jobject runtime, int id);
6369

@@ -98,6 +104,10 @@ class Runtime {
98104
static jmethodID GET_USED_MEMORY_METHOD_ID;
99105

100106
static bool s_mainThreadInitialized;
107+
108+
#ifdef APPLICATION_IN_DEBUG
109+
std::mutex m_fileWriteMutex;
110+
#endif
101111
};
102112
}
103113

test-app/runtime/src/main/cpp/com_tns_Runtime.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,20 @@ extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* env, jobject
231231
return success;
232232
}
233233

234+
extern "C" JNIEXPORT void Java_com_tns_Runtime_lock(JNIEnv* env, jobject obj, jint runtimeId) {
235+
auto runtime = TryGetRuntime(runtimeId);
236+
if (runtime != nullptr) {
237+
runtime->Lock();
238+
}
239+
}
240+
241+
extern "C" JNIEXPORT void Java_com_tns_Runtime_unlock(JNIEnv* env, jobject obj, jint runtimeId) {
242+
auto runtime = TryGetRuntime(runtimeId);
243+
if (runtime != nullptr) {
244+
runtime->Unlock();
245+
}
246+
}
247+
234248
extern "C" JNIEXPORT void Java_com_tns_Runtime_passUncaughtExceptionToJsNative(JNIEnv* env, jobject obj, jint runtimeId, jthrowable exception, jstring stackTrace) {
235249
auto runtime = TryGetRuntime(runtimeId);
236250
if (runtime == nullptr) {

test-app/runtime/src/main/java/com/tns/Runtime.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ private native void initNativeScript(int runtimeId, String filesPath, String nat
4848
private native int generateNewObjectId(int runtimeId);
4949

5050
private native boolean notifyGc(int runtimeId);
51+
private native void lock(int runtimeId);
52+
private native void unlock(int runtimeId);
5153

5254
private native void passUncaughtExceptionToJsNative(int runtimeId, Throwable ex, String stackTrace);
5355

@@ -610,9 +612,9 @@ private long getUsedMemory() {
610612
return usedMemory;
611613
}
612614

613-
public void notifyGc() {
614-
notifyGc(runtimeId);
615-
}
615+
public void notifyGc() { notifyGc(runtimeId); }
616+
public void lock() { lock(runtimeId); }
617+
public void unlock() { unlock(runtimeId); }
616618

617619
public static void initInstance(Object instance) {
618620
ManualInstrumentation.Frame frame = ManualInstrumentation.start("Runtime.initInstance");
@@ -643,6 +645,8 @@ private void createJSInstance(Object instance) {
643645
if (jsImpl != null) {
644646
File jsFile = new File(jsImpl.javaScriptFile());
645647
runModule(jsFile);
648+
} else {
649+
logger.write("Couldn't find JavaScriptImplementation annotation for class " + clazz.toString());
646650
}
647651
loadedJavaScriptExtends.put(clazz, jsImpl);
648652
}

0 commit comments

Comments
 (0)