@@ -2,17 +2,18 @@ package org.utbot.instrumentation.process
2
2
3
3
import com.jetbrains.rd.framework.*
4
4
import com.jetbrains.rd.framework.impl.RdCall
5
- import com.jetbrains.rd.framework.util.launchChild
6
5
import com.jetbrains.rd.util.ILoggerFactory
7
6
import com.jetbrains.rd.util.LogLevel
8
7
import com.jetbrains.rd.util.Logger
9
8
import com.jetbrains.rd.util.defaultLogFormat
10
9
import com.jetbrains.rd.util.lifetime.Lifetime
11
10
import com.jetbrains.rd.util.lifetime.LifetimeDefinition
12
11
import com.jetbrains.rd.util.lifetime.plusAssign
13
- import com.jetbrains.rd.util.threading.SingleThreadScheduler
14
- import kotlinx.coroutines.*
12
+ import kotlinx.coroutines.CompletableDeferred
15
13
import kotlinx.coroutines.channels.Channel
14
+ import kotlinx.coroutines.launch
15
+ import kotlinx.coroutines.runBlocking
16
+ import kotlinx.coroutines.withTimeoutOrNull
16
17
import org.utbot.common.*
17
18
import org.utbot.framework.plugin.api.util.UtContext
18
19
import org.utbot.instrumentation.agent.Agent
@@ -26,7 +27,7 @@ import org.utbot.instrumentation.rd.obtainClientIO
26
27
import org.utbot.instrumentation.rd.processSyncDirectory
27
28
import org.utbot.instrumentation.rd.signalChildReady
28
29
import org.utbot.instrumentation.util.KryoHelper
29
- import org.utbot.rd.UtSingleThreadScheduler
30
+ import org.utbot.rd.UtRdCoroutineScope
30
31
import org.utbot.rd.adviseForConditionAsync
31
32
import java.io.File
32
33
import java.io.OutputStream
@@ -35,7 +36,6 @@ import java.net.URLClassLoader
35
36
import java.security.AllPermission
36
37
import java.time.LocalDateTime
37
38
import java.time.format.DateTimeFormatter
38
- import java.util.concurrent.ArrayBlockingQueue
39
39
import java.util.concurrent.TimeUnit
40
40
import kotlin.system.measureTimeMillis
41
41
@@ -63,7 +63,6 @@ private object HandlerClassesLoader : URLClassLoader(emptyArray()) {
63
63
}
64
64
65
65
private typealias ChildProcessLogLevel = LogLevel
66
-
67
66
private val logLevel = ChildProcessLogLevel .Info
68
67
69
68
// Logging
@@ -75,14 +74,28 @@ private fun log(level: ChildProcessLogLevel, any: () -> Any?) {
75
74
System .err.println (LocalDateTime .now().format(dateFormatter) + " | ${any()} " )
76
75
}
77
76
77
+ // errors that must be address
78
78
private fun logError (any : () -> Any? ) {
79
79
log(ChildProcessLogLevel .Error , any)
80
80
}
81
81
82
+ private fun logException (e : Throwable ) {
83
+ log(ChildProcessLogLevel .Error ) { " $e |> ${e.stackTraceToString()} " }
84
+ }
85
+
86
+ // default log level for irregular useful messages that does not pollute log
82
87
private fun logInfo (any : () -> Any? ) {
83
88
log(ChildProcessLogLevel .Info , any)
84
89
}
85
90
91
+ // log level for frequent messages useful for debugging
92
+ private fun logDebug (any : () -> Any? ) {
93
+ log(ChildProcessLogLevel .Debug , any)
94
+ }
95
+
96
+ // log level for internal rd logs and frequent messages
97
+ // heavily pollutes log, useful only when debugging rpc
98
+ // probably contains no info about utbot
86
99
private fun logTrace (any : () -> Any? ) {
87
100
log(ChildProcessLogLevel .Trace , any)
88
101
}
@@ -119,9 +132,7 @@ suspend fun main(args: Array<String>) = runBlocking {
119
132
val pid = currentProcessPid.toInt()
120
133
val def = LifetimeDefinition ()
121
134
122
- SingleThreadScheduler (Lifetime .Eternal , " " )
123
-
124
- launchChild(Lifetime .Eternal ) {
135
+ launch {
125
136
var lastState = State .STARTED
126
137
while (true ) {
127
138
val current: State ? =
@@ -177,20 +188,27 @@ private fun <T, R> RdCall<T, R>.measureExecutionForTermination(block: (T) -> R)
177
188
this .set { it ->
178
189
runBlocking {
179
190
measureExecutionForTermination<R > {
180
- block(it)
191
+ try {
192
+ block(it)
193
+ } catch (e: Throwable ) {
194
+ logException(e)
195
+ throw e
196
+ }
181
197
}
182
198
}
183
199
}
184
200
}
185
201
186
202
private suspend fun ProtocolModel.setup (kryoHelper : KryoHelper , onStop : () -> Unit ) {
187
203
warmup.measureExecutionForTermination {
204
+ logDebug { " received warmup request" }
188
205
val time = measureTimeMillis {
189
206
HandlerClassesLoader .scanForClasses(" " ).toList() // here we transform classes
190
207
}
191
- logInfo { " warmup finished in $time ms" }
208
+ logDebug { " warmup finished in $time ms" }
192
209
}
193
210
invokeMethodCommand.measureExecutionForTermination { params ->
211
+ logDebug { " received invokeMethod request: ${params.classname} , ${params.signature} " }
194
212
val clazz = HandlerClassesLoader .loadClass(params.classname)
195
213
val res = instrumentation.invoke(
196
214
clazz,
@@ -199,31 +217,36 @@ private suspend fun ProtocolModel.setup(kryoHelper: KryoHelper, onStop: () -> Un
199
217
kryoHelper.readObject(params.parameters)
200
218
)
201
219
202
- logInfo { " sent cmd : $res " }
220
+ logDebug { " invokeMethod result : $res " }
203
221
InvokeMethodCommandResult (kryoHelper.writeObject(res))
204
222
}
205
223
setInstrumentation.measureExecutionForTermination { params ->
224
+ logDebug { " setInstrumentation request" }
206
225
instrumentation = kryoHelper.readObject(params.instrumentation)
226
+ logTrace { " instrumentation - ${instrumentation.javaClass.name} " }
207
227
Agent .dynamicClassTransformer.transformer = instrumentation // classTransformer is set
208
228
Agent .dynamicClassTransformer.addUserPaths(pathsToUserClasses)
209
229
instrumentation.init (pathsToUserClasses)
210
230
}
211
231
addPaths.measureExecutionForTermination { params ->
232
+ logDebug { " addPaths request" }
233
+ logTrace { " path to userClasses - ${params.pathsToUserClasses} " }
234
+ logTrace { " path to dependencyClasses - ${params.pathsToDependencyClasses} " }
212
235
pathsToUserClasses = params.pathsToUserClasses.split(File .pathSeparatorChar).toSet()
213
236
pathsToDependencyClasses = params.pathsToDependencyClasses.split(File .pathSeparatorChar).toSet()
214
237
HandlerClassesLoader .addUrls(pathsToUserClasses)
215
238
HandlerClassesLoader .addUrls(pathsToDependencyClasses)
216
239
kryoHelper.setKryoClassLoader(HandlerClassesLoader ) // Now kryo will use our classloader when it encounters unregistered class.
217
-
218
- logTrace { " User classes:" + pathsToUserClasses.joinToString() }
219
-
220
240
UtContext .setUtContext(UtContext (HandlerClassesLoader ))
221
241
}
222
242
stopProcess.measureExecutionForTermination {
243
+ logDebug { " stop request" }
223
244
onStop()
224
245
}
225
246
collectCoverage.measureExecutionForTermination { params ->
247
+ logDebug { " collect coverage request" }
226
248
val anyClass: Class <* > = kryoHelper.readObject(params.clazz)
249
+ logTrace { " class - ${anyClass.name} " }
227
250
val result = (instrumentation as CoverageInstrumentation ).collectCoverageInfo(anyClass)
228
251
CollectCoverageResult (kryoHelper.writeObject(result))
229
252
}
@@ -256,13 +279,12 @@ private suspend fun initiate(lifetime: Lifetime, port: Int, pid: Int) {
256
279
val kryoHelper = KryoHelper (lifetime)
257
280
logInfo { " kryo created" }
258
281
259
- val scheduler = UtSingleThreadScheduler { logInfo(it) }
260
282
val clientProtocol = Protocol (
261
283
" ChildProcess" ,
262
284
Serializers (),
263
285
Identities (IdKind .Client ),
264
- scheduler,
265
- SocketWire .Client (lifetime, scheduler, port),
286
+ UtRdCoroutineScope . scheduler,
287
+ SocketWire .Client (lifetime, UtRdCoroutineScope . scheduler, port),
266
288
lifetime
267
289
)
268
290
val (sync, protocolModel) = obtainClientIO(lifetime, clientProtocol)
@@ -290,6 +312,7 @@ private suspend fun initiate(lifetime: Lifetime, port: Int, pid: Int) {
290
312
logInfo { " starting instrumenting" }
291
313
deferred.await()
292
314
} catch (e: Throwable ) {
293
- logError { " Terminating process because exception occurred: ${e.stackTraceToString()} " }
315
+ logError { " Terminating process because exception occurred" }
316
+ logException(e)
294
317
}
295
318
}
0 commit comments